您的位置:首页 > 其它

【POJ 2154】Color(置换群)

2016-05-22 19:20 441 查看
Color

Time Limit: 2000MS Memory Limit: 65536K

Total Submissions: 9265 Accepted: 3010

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

[题意][将正n边形的n个顶点用n种颜色染色,问有多少种方案(答案mod p,且可由旋转互相得到的算一种)]

【题解】【与前面几题相似,但此题没有旋转,但数据范围相当恶心,所以,要优化】

∑ni=1ngcd(i,n)

=∑ni=1∑nd=1n[(i,n)=d]

=∑[d|n]∗φ(d n)∗nd

按照这个公式筛欧拉函数,但因为范围过大,所以,不可能全部筛出,筛一半,另一半,用下面的方法

根号n的时间内求一个数的phi
inline int find(int m)
{
int i,k=m,l=m;
for (i=2;i*i<=m;++i)
if (!(l%i))
{
k=k-k/i;
do{  l/=i;  }while(!(l%i));
}
if (l>1) k=k-k/l;
return k;
}


由于范围过大,枚举的时候只能枚举一半,而且要谨慎使用long long

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int prime[100010],phi[100010];
int m,n,mod;
bool p[100010];

inline void shai(int m)
{
int i,j;
phi[1]=1; p[1]=1;
for(i=2;i<=m;++i)
{
if(!p[i])  prime[++prime[0]]=i,phi[i]=i-1;
for(j=1;j<=prime[0];++j)
{
if(i*prime[j]>m) break;
p[i*prime[j]]=1;
if(!(i%prime[j]))
{phi[i*prime[j]]=phi[i]*prime[j]; break;}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
return;
}
ll poww(int x,int q)
{
if(!q) return 1;
if(q==1) return x%mod;
if(q==2) return x*x%mod;
if(q%2)
{ll sum=poww(x,q/2)%mod;  sum=sum*sum*x%mod;  return sum%mod;}
else
{ll sum=poww(x,q/2)%mod; sum*=sum; return sum%mod; }
}
inline ll get_phi(int x)
{
if(x<=70000) return phi[x];
ll ans=x;
int i;
for(i=2;i*i<=x;++i)
if(!(x%i))
{
ans=ans*(i-1)/i;
while(!(x%i)) x/=i;
}
if(x>1) ans=ans*(x-1)/x;
return ans%mod;
}

int main()
{
int i,j;
shai(100000);
scanf("%d",&n);
for(j=1;j<=n;++j)
{
ll ans=0;
scanf("%d%d",&m,&mod);
for(i=1;i*i<=m;++i)
if(!(m%i))
{
ll s1=get_phi(i); ll s2=get_phi(m/i);
if(m/i==i) ans=(ans+s2*poww(m%mod,i-1))%mod;
else ans=(ans+s2*poww(m%mod,i-1))%mod,
ans=(ans+s1*poww(m%mod,m/i-1))%mod;
}
printf("%I64d\n",ans%mod);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 置换群