polyd计数问题,题意是给你n个珠子n种染料,可以旋转,可以有多少种不等价的染色方案。ps:一定要慎重处理取余的运算,不是素数的mod,个人拙见,如不对请指正。
#include<cstdio>
#include<map>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
ll n;
int mod;
int T;
ll mod_pow(ll x,ll n,int MOD)
{
ll res=1;
while(n>0)
{
if(n&1)res=res*x%MOD;
x=x*x%MOD;
n>>=1;
}
return res;
}
map<int ,int> prime_factor(int n)
{
map<int , int>res;
for(int i=2; i*i<=n; i++)
{
while(n%i==0)
{
++res[i];
n/=i;
}
}
if(n!=1)
res[n]=1;
return res;
}
vector<int> divisor(int n)
{
vector<int> res;
for(int i=1; i*i<=n; i++)
{
if(n%i==0)
{
res.push_back(i);
if(i!=n/i)res.push_back(n/i);
}
}
return res;
}
void solve()
{
map<int ,int>primes = prime_factor(n);
vector<int>divs=divisor(n);
ll res=0;
for(int i=0; i<divs.size(); i++)
{
ll euler = divs[i];
for(map<int ,int>::iterator it = primes.begin(); it!=primes.end(); ++it)
{
int p = it->first;
if(divs[i]%p == 0)euler = euler / p * (p - 1);
}
res+=euler*mod_pow(n,n/divs[i]-1,mod)%mod;
res%=mod;
}
printf("%lld\n",res);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%lld %d",&n,&mod);
solve();
}
return 0;
}