码迷,mamicode.com
首页 > 其他好文 > 详细

hiho 挑战赛7(有钱就是任性-dp与质数的因子)

时间:2015-03-02 22:35:26      阅读:493      评论:0      收藏:0      [点我收藏+]

标签:

题目4 : 有钱就是任性

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

俗话说,有钱就是任性。我们的高富帅鱼丸同学打算去看电影。鱼丸到了电影院以后,发现座位的编号正好是1到200。

但是有一些座位号对应的座位坏掉了,没法坐,不妨假设还剩下N个能坐的椅子。电影的老板告诉鱼丸,如果你要包下一个集合S里的所有椅子,就要付出这些椅子的编号的最小公倍数的钱。鱼丸很任性地同意了。

来这里玩了很多天以后,鱼丸发现自己正好来了2N-1天,并且由于他非常任性,对于这N个椅子的每一种可能的非空子集,他都包下过来看电影。鱼丸大少爷虽然不在乎花了多少钱,但你毕竟是他的助理,于是你想知道鱼丸一共花了多少钱。由于钱的数量实在太大,请对答案mod 109+7之后输出。

输入

第一行输入一个数N(1 <= N <= 200),表示能做的椅子的数量。

接下来一行N个1到200之间的整数,用空格隔开。

输出

一行输出答案。

样例输入
2
2 4
样例输出
10

本题是dp,但是map存不下那么大的数(lcm(1,2,...,200)),所以考虑压缩

容易想到≤n的数p>sqrt(n)的只出现一次,

所以可以将它们压缩a1*a2*...*a[m-1]*p=n 压缩为a1*a2*...*a[m-1]

f(i)表示lcm=i的次数

因为让f(a1*a2*...*a[m-1])+=p*f(a1*a2*...*a[m-1]*p)不影响结果就可以了,

值得注意的是f()中的数可能已经超过F了,要先取模以防溢出




#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<map>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define MAXN (2000+10)
#define N (200)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
void upd(ll &a,ll b){a=(a+b)%F;}
int n,a[MAXN],p[MAXN],tot=0;
bool b[MAXN]={0};
map<ll,ll> f[2];
ll gcd(ll a,ll b){if (b==0) return a;return gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
void make_prime(int n)
{
	Fork(i,2,n)
	{
		if (!b[i]) p[++tot]=i;
		For(j,tot)
		{
			if (i*p[j]>n) break;
			b[i*p[j]]=1;
			if (i%p[j]==0) break;  
		}
	}
}
int cnt[MAXN]={0};
ll pw2[MAXN]={1,2,4,8,16,32,64,128,256,512,1024,
2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,
2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,73741817,
147483634,294967268,589934536,179869065,359738130,719476260,438952513,877905026,755810045,511620083,
23240159,46480318,92960636,185921272,371842544,743685088,487370169,974740338,949480669,898961331,
797922655,595845303,191690599,383381198,766762396,533524785,67049563,134099126,268198252,536396504,
72793001,145586002,291172004,582344008,164688009,329376018,658752036,317504065,635008130,270016253,
540032506,80065005,160130010,320260020,640520040,281040073,562080146,124160285,248320570,496641140,
993282280,986564553,973129099,946258191,892516375,785032743,570065479,140130951,280261902,560523804,
121047601,242095202,484190404,968380808,936761609,873523211,747046415,494092823,988185646,976371285,
952742563,905485119,810970231,621940455,243880903,487761806,975523612,951047217,902094427,804188847,
608377687,216755367,433510734,867021468,734042929,468085851,936171702,872343397,744686787,489373567,
978747134,957494261,914988515,829977023,659954039,319908071,639816142,279632277,559264554,118529101,
237058202,474116404,948232808,896465609,792931211,585862415,171724823,343449646,686899292,373798577,
747597154,495194301,990388602,980777197,961554387,923108767,846217527,692435047,384870087,769740174,
539480341,78960675,157921350,315842700,631685400,263370793,526741586,53483165,106966330,213932660,
427865320,855730640,711461273,422922539,845845078,691690149,383380291,766760582,533521157,67042307,
134084614,268169228,536338456,72676905,145353810,290707620,581415240,162830473,325660946,651321892,
302643777,605287554,210575101,421150202,842300404,684600801,369201595,738403190,476806373,953612746,
907225485,814450963,628901919,257803831,515607662,31215317,62430634,124861268,249722536,499445072
};
bool use[MAXN]={0};
int main()
{
//	freopen("hiho1113.in","r",stdin);
//	freopen("hiho1113.out","w",stdout);
	make_prime(200);
	cin>>n;
	For(i,n) cin>>a[i],cnt[a[i]]++;

	bool ct=0;
	f[0][1]=1; //假设一开始有一个空集 lcm(φ)=1的 ,显然lcm(φ,a,b,c..)=lcm(a,b,c..) 
	// 后面 则是 {解集}+元素i 
	ForD(j,tot)
		if (p[j]*p[j]>N) //若p[j]*k=N=200 则 k<sqrt(N)<p[j] 
		{
			for(int k=1;k<=N/p[j];k++)
			{
				int i=k*p[j];use[i]=1;
				if (!cnt[i]) continue;
				for(map<ll,ll>::iterator it=f[ct].begin();it!=f[ct].end();it++)
				{
					ll c=it->first,v=it->second;
					upd(f[ct^1][c],f[ct][c]); //有可能之前在lcm时改过 
					upd(f[ct^1][lcm(c,i)],mul(f[ct][c],sub(pw2[cnt[i]],1)));
				}
				f[ct].clear();
				ct^=1;
			}
			//显然p[j]最多 出现1次,且之后不出现,故 把p[j]"删"去不对答案影响 f(i)表示 lcm(..)=i的数的个数 
			//eg cost=2*f(2)+2*56*f(2*56) = 2*F(2) F(2)=(f(2)+56*f(2*56))  
			//添加17 ->  F(2*17)=f(2*17)+56*f(2*17*56)
			for(map<ll,ll>::iterator it=f[ct].begin();it!=f[ct].end();it++)
			{
				ll c=it->first,v=it->second;
				if (c%p[j]==0) upd(f[ct^1][c/p[j]],mul(v,p[j]));
				else upd(f[ct^1][c],v);
			}
			f[ct].clear();
			ct^=1;
		}
	For(i,N)
	{
		if (use[i]) continue;
		if (!cnt[i]) continue;
		for(map<ll,ll>::iterator it=f[ct].begin();it!=f[ct].end();it++)
		{
			ll c=it->first,v=it->second;
			upd(f[ct^1][c],f[ct][c]); //有可能之前在lcm时改过 
			upd(f[ct^1][lcm(c,i)],mul(f[ct][c],sub(pw2[cnt[i]],1)));
		}
		f[ct].clear();
		ct^=1;
	}
	
	
	ll ans=0;
	
	for(map<ll,ll>::iterator it=f[ct].begin();it!=f[ct].end();it++)
		upd(ans,mul((it->first)%F,(it->second)%F));
	cout<<sub(ans,1)<<endl;
	
	
	
	return 0;
}





hiho 挑战赛7(有钱就是任性-dp与质数的因子)

标签:

原文地址:http://blog.csdn.net/nike0good/article/details/44023807

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!