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 }
uva 12546

 

 

posted @ 2013-11-27 20:22  破晓べ  阅读(451)  评论(0编辑  收藏  举报