题目:4335
思路:对n!分成三部分,小于euler(mod)的部分,剩下的,根据能否整除euler(mod),分成循环节部分和剩余的部分(暴力)
参考了这里, here
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
typedef unsigned __int64 LL;
LL mod,b,M;
LL euler(LL x)
{
LL i,res=x;
for(int i=2;i*i<=x;i++)
if(x%i==0)
{
res=res/i*(i-1);
while(x%i==0)
x/=i;
}
if(x>1)
res=res/x*(x-1);
return res;
}
LL Pow(LL a,LL b)
{
LL ans=1;
while(b)
{
if(b&1)
{
b--;
ans=(ans*a)%mod;
}
else
{
b/=2;
a=(a*a)%mod;
}
}
return ans;
}
int main()
{
int t;
cin>>t;
for(int cases=1;cases<=t;cases++)
{
cin>>b>>mod>>M;
cout<<"Case #"<<cases<<": ";
LL eul=euler(mod);
if(mod==1)
{
if(b==0)
{
if(M==18446744073709551615LLU)
cout<<"18446744073709551616"<<endl;
else
cout<<M+1<<endl;
}
else
cout<<0<<endl;
}
else
{
LL cnt=1,pnt=0;
LL ans=0;
LL fac=1;
for(pnt=0;pnt<=M;pnt++)
{
if(fac>=eul)
break;
if(Pow(pnt,fac)==b)
ans++;
fac*=pnt+1;
}
fac%=eul;
for(;pnt<=M;pnt++)
{
if(fac==0)
break;
if(Pow(pnt,fac+eul)==b)
ans++;
fac=fac*(pnt+1)%eul;
}
if(pnt<=M)
{
LL tmp=0;
for(LL i=0;i<mod;i++)
if(Pow(pnt+i,eul)==b)
tmp++;
LL miao=(M-pnt+1)/mod;
ans+=miao*tmp;
miao=(M-pnt+1)-miao*mod;
for(LL i=0;i<miao;i++)
if(Pow(pnt+i,eul)==b)
ans++;
}
cout<<ans<<endl;
}
}
return 0;
}