牛客多校2019——Big Integer——欧拉定理,质因数分解
官方给的题解是这样的:
直接从别的博客复制过来了,有几点需要补充解释一下:
d为满足 的最小正整数,求它的目的是为了更方便的去求 ,因为它一定是d的倍数。
求g的时候,指数向上取整是为了保证j次方之后一定为d的倍数,当然大概率是会多乘几个质因数
强调k<=30这个界限是因为,在 的极限情况下,k最多不会超过30,2^30=1073741824。而在这之上时k/j向上取整只能为1,所以在这之后所加的值一定相同
贴代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int pri[105],fac[105];
int num;
void uniqueDecompose(ll x){
num=0;
for(int i=2;i*i<=x;i++){
if(x%i==0){
pri[num]=i;
fac[num]=0;
while(x%i==0){
fac[num]++;
x=(x/i);
}
++num;
}
}
if(x>1) pri[num]=x,fac[num++]=1;
}
ll qmul(ll x,ll y,ll m){
ll res=0;
while(y){
if(y&1){
res=(res+x)%m;
}
x=(x+x)%m;
y>>=1;
}
return res;
}
ll qpow(ll a,ll n,ll m){
ll res=1;
while(n){
if(n&1){
res=qmul(res,a,m)%m;
}
a=qmul(a,a,m)%m;
n>>=1;
}
return res;
}
int main(){
int t;
cin>>t;
while(t--){
ll n,m,p;
cin>>p>>n>>m;
if(p==2||p==5){
puts("0");
continue;
}
ll phi=6ll*(p-1);
ll d=1e18;
for(ll i=2;i*i<=phi;i++){
if(phi%i==0){
if(qpow(10,i,9ll*p)==1)
d=min(d,i);
if(qpow(10,phi/i,9ll*p)==1)
d=min(d,phi/i);
}
}
uniqueDecompose(d);
ll g=1; ll ans=0;
for(int j=1;j<=min(m,30ll);j++){
g=1;
for(int i=0;i<num;i++){
g*=qpow(pri[i],ceil(1.0*fac[i]/j),2e9);
}
ans+=n/g;
}
if(m>30)
ans+=(m-30)*(n/g);
cout<<ans<<endl;
}
return 0;
}