求满足$n^{n!}equiv b $(mod p)的n的数量。
思路:n!太大了,这一题要用到降幂公式:
A^x = A^(x % Phi(C) + Phi(C)) (mod C) (x>=Phi(C))
所以可以把n的取值分为三部分。
1:n≤phi(C),这部分直接暴力
2:当n!%phi(c)=0时,(n+1)!%phi(c)=0,这时公式可化为求A^(phi(c))
所以第二部分是n!%phi(c)!=0时,也是暴力。
3:最后一部分由于幂指数不变,根据鸽巢原理求出其循环节然后算出贡献。
注意特判P为1的情况(P为1时,m可能爆ull)
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector> #include<string> #define ll unsigned long long #define PI acos(-1.0) #define F first #define S second #define pb push_back #define debug(x); printf("debug%lld ",x); #define des(x); printf("des:%s ",x+1); const ll INF=0x3f3f3f3f3f3f3f3f; const int inf=0x3f3f3f3f; //const ll mod=1e9+7; ll mod; using namespace std; int t; ll m,b,p; const int N=1e5+5; ll num[N]; ll oula(ll x) { ll temp=x; for(ll i=2;i*i<=x;i++) { if(x%i==0) { temp=temp/i*(i-1); while(x%i==0) { x/=i; } } } if(x>1) temp=temp/x*(x-1); return temp; } ll QuickPow(ll x,ll N) { ll res = x; ll ans = 1ll; while(N) { if(N&1) { ans=ans*res%mod; } res=res*res%mod; N=N>>1; } return ans; } int main() { scanf("%d",&t); for(int tt=1;tt<=t;tt++) { scanf("%I64u%I64u%I64u",&b,&p,&m); printf("Case #%d: ",tt); ll phi=oula(p); mod=p; ll i=0; ll ans=0; ll fac=1; if(p==1) { if(m==18446744073709551615ll) { printf("18446744073709551616 "); } else printf("%I64u ",m+1); continue; } for(i;i<=m&&fac<=phi;i++) { if(QuickPow(i,fac)==b) { ans++; } fac*=(i+1); } fac%=phi; for(i;fac&&i<=m;i++) { if(QuickPow(i,fac+phi)==b) ans++; fac=(fac*(i+1))%phi; } if(i<=m) { ll cnt=0; for(ll j=0;j<p;j++) { num[j]=0; if(QuickPow(i+j,phi)==b) { num[j]++; cnt++; } } ll total=(m-i+1)/p; ans+=total*cnt; total=(m-i+1)%p; for(ll j=0;j<total;j++) { if(num[j]) ans++; } } printf("%I64u ",ans); } return 0; }