测试地址:Color
题目大意:有
做法:前几天POJ炸了,所以拖到今天才写这一篇……
这一题需要用到Polya定理(真名不是这个o,但是那个字符不会打QAQ)+欧拉函数。
首先看Polya定理的内容:对于一个置换群
其中
那么再看这一题,容易看出
设
考虑到模意义下乘以一个分数比较困难,所以我们直接把
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
ll T,N,P,tot=0,fac[25],num[25],ans;
void find_factor()
{
ll s=N;
tot=0;
for(ll i=2;i*i<=s;i++)
if (!(s%i))
{
fac[++tot]=i;
num[tot]=0;
while(!(s%i)) s/=i,num[tot]++;
}
if (s>1) fac[++tot]=s,num[tot]=1;
}
ll phi(ll x)
{
ll s=x,ss=x;
for(ll i=2;i*i<=s;i++)
if (!(s%i))
{
ss=ss/i*(i-1);
while(!(s%i)) s/=i;
}
if (s>1) ss=ss/s*(s-1);
return ss;
}
ll power(ll a,ll b)
{
ll s=a,sum=1;
while(b)
{
if (b&1) sum=(sum*s)%P;
b>>=1;s=(s*s)%P;
}
return sum;
}
void dfs(int i,ll d)
{
if (i>tot)
{
ans=(ans+phi(N/d)*power(N,d-1))%P;
return;
}
for(int j=0;j<=num[i];j++)
{
dfs(i+1,d);
d*=fac[i];
}
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld",&N,&P);
find_factor();
ans=0;
dfs(1,1);
printf("%lld
",ans);
}
return 0;
}