hdu4335 欧拉降幂
hdu4335 What is N?
传送门
题意
给定\(b(0\leq b<p),p(1\leq p\leq 1e5),m(1\leq m\leq 2^{64}-1)\),计算有多少\(n\)满足:
\[\begin{cases}
n^{n!}\equiv b(mod\ p)\\
0\leq n\leq m
\end{cases}\]
题解
欧拉降幂公式:
\(a^k\equiv a^{k\% \varphi(m)+\varphi(m)}(mod\ m)\)
满足条件的\(n\)分成三个部分:
1.\(n!\leq \varphi(p)\),暴力计算
2.\(n!>\varphi(p)\)并且\(n!\% \varphi(p)\neq 0\),通过欧拉降幂公式暴力计算
3.\(n!>\varphi(p)\)并且\(n!\% \varphi(p)==0\),\(n^{n!\% \varphi(p)+\varphi(p)}\% p=(n\% p)^{\varphi(p)}\% p\),所以所有剩余的\(n\)的取值存在一个长度是\(p\)的循环节
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PLI pairB<LL,int>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxp=100010;
int T;
ULL b,p,m,a[maxp];
ULL get_phi(ULL x){
ULL ans=x;
for(ULL i=2;i*i<=x;i++){
if(x%i==0){
ans=ans/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) ans=ans/x*(x-1);
return ans;
}
ULL qp(ULL a,ULL b,ULL mod){
ULL res=1%mod;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int main(){
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%llu %llu %llu",&b,&p,&m);
printf("Case #%d: ",cas);
if(p==1){
if(m==18446744073709551615ULL) printf("18446744073709551616\n");
else printf("%llu\n",m+1);
continue;
}
ULL phi=get_phi(p);
ULL ans=0,fac=1,i;
for(i=0;i<=m && fac<=phi;i++){
if(qp(i,fac,p)==b) ans++;
fac*=i+1;
}
if(fac){
fac%=phi;
for(;i<=m && fac;i++){
if(qp(i,fac+phi,p)==b) ans++;
fac=fac*(i+1)%phi;
}
}
if(i<=m){
ULL cnt=0;
for(ULL j=0;j<p;j++){
a[j]=qp(i+j,phi,p);
if(a[j]==b) cnt++;
}
ULL num=(m-i+1)/p;
ans+=num*cnt;
ULL rest=(m-i+1)%p;
for(ULL j=0;j<rest;j++){
if(a[j]==b) ans++;
}
}
printf("%llu\n",ans);
}
}

浙公网安备 33010602011771号