poj 2154 color——polya

这道题wa到我快吐了……主要是因为计算欧拉函数的时候是先乘再除的,因该反过来,但是不知道这样为什么会wa,还有就是素数筛写搓了,标程的素数筛改成我的就wa了……

这道题n很大,我们套用polya公式的时候就不能枚举i了,只能反过来枚举循环的长度L

证明就不说了,别的解题报告都有……

对于每一个长度L,都有若干i使得gcd(n,i)=n/L,那么在polya公式里面,n^gcd(n,i)就有euler(L)个。因为L|n,所以只用枚举到L*L<n

后来才发现p不是素数,所以在除总数n的时候不可以用素数取逆方法直接算,就用的标程的方法,如下注释。

还有就是,现在还不知道哪里应该取模哪里不应该取模,哪里应该强制类型转换……很纠结啊………………………………

上代码:

a27400 2154 Accepted 948K 1313MS G++ 1476B 2011-08-24 14:54:54
#include <iostream>  
#include
<cstdlib>
#include
<algorithm>
#include
<cstdio>
#include
<vector>

using namespace std;

int isprime[50001];
int prime[8001];
int tot;

void getprime() //以后就用这个素数筛模版好了……
{
for(int i=2;i<=50000;i++)if(!isprime[i])
{
prime[tot
++]=i;
for(int j=1;j*i<=50000;j++)
{
isprime[i
*j]=1;
}
}
tot
--;
}

int euler(int n)
{
int i;
int _n=n;
int total=n;
for(i=0;i<=tot&&prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
total
=total/prime[i]*(prime[i]-1);
while(_n%prime[i]==0)
{
_n
/=prime[i];
}
}
}
if(_n!=1)
{
total
=total/_n*(_n-1);
}
return total;
}

int quickmod(int a,int n,int p)
{
if(n==0)
return 1%p;
if(n==1)
return a%p;
a
%=p;
long long ans=quickmod(a,n/2,p)%p;
ans
=ans*ans%p;
if(n&1)
ans
=ans*a%p;
return (int)ans%p;
}

int main()
{
int Case;
getprime();
scanf(
"%d",&Case);
int n,p;
while(Case--)
{
scanf(
"%d %d",&n,&p);
int ans=0,i;
for(i=1;i*i<n;i++)
if(n%i==0)
{
ans
=(ans+euler(i)%p*quickmod(n,n/i-1,p)+euler(n/i)%p*quickmod(n,i-1,p))%p;;//这里的i-1代表已经除以整个置换数n了,原本是expmod(n,i),最后要除以n的
}
if(i*i==n)
ans
=(ans+euler(i)*quickmod(n,i-1,p))%p;
cout
<<ans<<endl;
}
return 0;
}

你可能感兴趣的:(color)