題意:給定p, b(0<=b<p<=10^5)和m(1<=m<2^64),問有多少個n滿足n^(n!)=b (mod p)。
思路:首先要知道這個結論:
當n!<Phi(C)時,此時我們暴力解決就可。
當n!大於phi(P)的時候,就需要用上面的降冪公式了。
方法還是暴力,n!%phi(p)會出現0,這是必然的,至少n>=phi(p)爲0,
那麼(n+1)!%phi(p)也爲0,這便出現了重複,轉變爲n^(phi(p))%p==b的問題了。
固定了指數,根據鴿巢原理,餘數是循環的,那麼只要找出p個的結果,之後通過循環節求解便可以了。
Trick:當P爲1的時候,b爲0,這時候答案是m+1,不過m可能爲2^64-1,如果加1的話就會溢出。
#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
const int maxn=1e5+50;
ll arr[maxn];
ll eular(ll n)
{
ll res=n;
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
res=res-res/i;
while(n%i==0)
{
n/=i;
}
}
}
if(n>1)
{
res=res-res/n;
}
return res;
}
ll power(ll a,ll b,ll mod)
{
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
int cas=0;
while(t--)
{
ll b,p,m;
scanf("%llu%llu%llu",&b,&p,&m);
printf("Case #%d: ",++cas);
if(p==1)
{
if(m==18446744073709551615ll)
printf("18446744073709551616\n");
else
printf("%llu\n",m+1);
continue;
}
ll ph=eular(p);
ll fac=1;
ll i;
ll ans=0;
for(i=0;i<=m&&fac<ph;i++)
{
if(power(i,fac,p)==b)
ans++;
fac=fac*(i+1);
}
fac%=ph;
for(;i<=m&&fac;i++)
{
if(power(i,fac+ph,p)==b)
{
ans++;
}
fac=(fac*(i+1))%ph;
}
if(i<=m)
{
ll cnt=0;
for(ll j=0;j<p;j++)
{
arr[j]=power(i+j,ph,p);
if(1ll*power(i+j,ph,p)==b)
{
cnt++;
}
}
ll num=(m-i+1)/p;// 循環節長度
ans+=num*cnt;
num=(m-i+1)%p;// 剩餘部分
for(ll j=0;j<num;j++)// 這裏是開區間 因爲num等於0時說明正好能整除 故不進行操作
{
if(arr[j]==b)
{
ans++;
}
}
}
printf("%llu\n",ans);
}
return 0;
}