uva 12546
题意:
给你一个数n,已经分解过质因子,其中有m个因子a1,a2...am和他们的个数c1,c2....cm,设pair(p,q)满足gcd(p,q)==n && 1<=P<=q<=n,则一共可以找出很多个pair(p1,q1),pair(p2,q2)...pair(pk,qk) 求f(n) = p1+q1+p2+q2.....+pk+qk.
想法:
比赛的时候用的2^15的状压,对于一个状态,1代表pair里的第一个数字是满的,即ai^ci,0代表不是满的,可以取ai^0到ai^ci,那么,对于一种状态1001,SUM可以表示成a1^c1*(1+a2+a2^2+...+a2^c2)*(1+a3+a3^2+...+a3^c2)*a4^c4,对于这些个sum,有可能在多个pair中出现,所以还要乘以一个系数,所以我们要求出,对于这个状态,它的合法的pair有多少种,显然,对于1001这个状态cnt = (c1+1)*1*1*(c4+1).就这样把每个状态算出来求和就是结果了,最后还要加上一个少加的n,因为(n,n)这一对只算了1个。
赛后发现想麻烦了,其实可以直接(1+a1+a1^2...(c1+1)*a1^c1)*(1+a2+a2^2...(c2+1)*a2^c2)*.....*(1+am+am^2...(cm+1)*am^cm)+n,系数直接乘进去和上面那种方法是等价的,代码量却可以缩减很多!!智商啊~
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 typedef long long LL; 6 #define MOD 1000000007 7 int main(){ 8 int T,c,a,b,cases=0; 9 scanf("%d",&T); 10 while(T--){ 11 cases++; 12 scanf("%d",&c); 13 LL ans=1,flag=1; 14 for(int i=0;i<c;i++){ 15 LL tem=1,fac=1;; 16 scanf("%d%d",&a,&b); 17 for(int i=0;i<b;i++){ 18 fac = fac * a%MOD; 19 tem = (tem + fac) %MOD; 20 } 21 tem = (tem + fac*b%MOD)%MOD; 22 flag = flag*fac%MOD; 23 ans = ans * tem %MOD; 24 } 25 ans = (ans + flag) % MOD; 26 printf("Case %d: %lld\n",cases,ans); 27 } 28 return 0; 29 }