poj-2154-polya+euler函数

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 11758   Accepted: 3783

Description

Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the necklace can be produced. You should know that the necklace might not use up all the N colors, and the repetitions that are produced by rotation around the center of the circular necklace are all neglected. 

You only need to output the answer module a given number P. 

Input

The first line of the input is an integer X (X <= 3500) representing the number of test cases. The following X lines each contains two numbers N and P (1 <= N <= 1000000000, 1 <= P <= 30000), representing a test case.

Output

For each test case, output one line containing the answer.

Sample Input

5
1 30000
2 30000
3 30000
4 30000
5 30000

Sample Output

1
3
11
70
629

Source

POJ Monthly,Lou Tiancheng
  n种颜色的珠子组成一个长度为n的圆环,旋转能够到达的属于重复状态,问一共有多少种不同的方案。
  由polya定理可知 ans=SUM{ ngcd(k,n) |  0<=k<n} / n ,n<1e9  如果直接算的话肯定会T。由于所有的gcd(k,n)都是n的因子,可以考虑对
相同的因子分成一组,这样找到每一组的个数就好办了, ans=1/n * SUM{ s(d)*nd |  d|n ,s(d)为使得gcd(k,n)=d成立的k的个数 },
gcd(k,n)==d   -->  gcd(k/d,n/d)==1  --> phi(n/d)  。 所以得出s(d)=phi(n/d) ,枚举一下n的因子统计答案就好了。
  在计算phi的时候先把sqrt(1e9)之内的素数筛出来再计算会更快,否则会超时。
  
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<map>
 5 #include<set>
 6 #include<vector>
 7 #include<algorithm>
 8 #include<cmath> 
 9 using namespace std;
10 #define LL long long 
11 #define PI acos(-1.0)
12 #define N 33333
13 int mod;
14 bool isp[N+10];
15 vector<int>prime;
16 void init(){
17     int m=sqrt(N+0.5);
18     for(int i=2;i<=N;i++){
19         if(!isp[i]){
20             prime.push_back(i);
21             for(int j=i*i;j<=N;j+=i)isp[j]=1;
22         }
23     }
24 }
25 int qpow(int a,int b,int m){
26     a%=m;
27     int r=1;
28     while(b){
29         if(b&1) r=r*a%m;
30         b>>=1;
31         a=a*a%m;
32     }
33     return r%m;
34 }
35 int euler(int n){
36     int m=sqrt(n+0.5);
37     int ans=n;
38     for(int i=0;prime[i]<=m;++i){
39         if(n%prime[i]==0){
40         ans=ans/prime[i]*(prime[i]-1);
41         while(n%prime[i]==0) n/=prime[i];
42         }
43     }
44     if(n>1) ans=ans/n*(n-1);
45     return ans%mod;
46 }
47 int main()
48 {
49     int t,n,i,j,k,d;
50     init();
51     scanf("%d",&t);
52     while(t--){
53         scanf("%d%d",&n,&mod);
54         int ans=0;
55         for(i=1;i*i<n;++i){
56             if(n%i==0){
57                 (ans+=(euler(n/i)*qpow(n,i-1,mod)%mod))%=mod;
58                 
59                 (ans+=(euler(i)*qpow(n,n/i-1,mod)%mod))%=mod;
60             }
61         }
62         if(i*i==n) (ans+=(euler(i)*qpow(n,i-1,mod)%mod))%=mod;
63         cout<<ans<<endl;
64     }
65     return 0;
66 }

 

posted @ 2018-08-09 16:48  *zzq  阅读(186)  评论(0编辑  收藏  举报