求用m种颜色给n个物品染色的方案数--旋转
根据Polya定理有
此题中m=n
#include<bits/stdc++.h>
using namespace std;
int t,n,p;
int euler(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0) n/=i;
}
}
if(n>1) ans-=ans/n;
return ans;
}
long long pow(long long a,int k,long long mod)
{
long long b=1;
while(k)
{
if(k&1) b=b*a%mod;
a=a*a%mod;
k>>=1;
}
return b;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&p);
long long ans=0;
int i;
for(i=1;i*i<n;++i)
{
if(n%i) continue;
ans+=euler(n/i)%p*pow(n%p,i-1,p)%p+euler(i)%p*pow(n%p,n/i-1,p)%p;
}
if(i*i==n) ans+=euler(i)%p*pow(n%p,i-1,p)%p;
printf("%lld\n",ans%p);
}
return 0;
}
m=3,旋转+对称
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n;
int euler(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0) n/=i;
}
}
if(n>1) ans-=ans/n;
return ans;
}
long long pow_(long long a,int k)
{
long long b=1;
while(k)
{
if(k&1) b=b*a;
a=a*a;
k>>=1;
}
return b;
}
int main()
{
while(scanf("%d",&n))
{
if(n==-1) break;
if(n==0) {printf("0\n");continue;}
long long ans=0;int i=1;
for(i=1;i*i<n;++i)
{
if(n%i) continue;
ans+=euler(n/i)*pow_(3,i)+euler(i)*pow_(3,n/i);
}
if(i*i==n) ans+=euler(i)*pow_(3,i);
ans/=n;
ans+=(pow_(3,(n+1)/2)+pow_(3,n/2+1))/2;
printf("%lld\n",ans/2);
}
return 0;
}