很好的题解思路博客
代码思路和上面博客一样
#include
using namespace std;
typedef long long ll;
ll n,m,p,a[105],b[105],r,cnt;
ll cal(ll x){//分解x得到分解后的因子a和指数b
cnt=0;
int j=2;
while(j*j<=x){
if(x%j==0){
cnt++;
a[cnt]=j,b[cnt]=0;
while(x%j==0)b[cnt]++,x/=j;
}
j++;
}
if(x>1){
cnt++;
a[cnt]=x,b[cnt]=1;
}
}
ll fp(ll x,ll y,ll mod){
ll ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;
y/=2;
}
return ret;
}
ll solve(ll n,ll m,ll x){//求有多少对i,j满足10^(i^j)%p==1
ll mx=0,ans=0;
cal(x);
for(int i=1;i<=cnt;i++)mx=max(mx,b[i]);//唯一分解中最大的指数
for(int i=1;i<=min(mx,m);i++){
ll ret=1;
for(int j=1;j<=cnt;j++){
int s=(b[j]+i-1)/i;
for(int k=0;k<s;k++)ret=ret*a[j];
}
ans+=n/ret;
}
if(m>mx){
ll ret=1;
for(int i=1;i<=cnt;i++)ret=ret*a[i];
ans+=(m-mx)*(n/ret);
}
return ans;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>p>>n>>m;
if(p==2||p==5){
puts("0");
continue;
}
if(p==3)r=3;//如果p==3要特判
else {
r=p-1;//r为循环节
cal(r);
for(int i=1;i<=cnt;i++)//看是否能在r的因子中找到更小的循环节
for(int j=0;j<b[i];j++)if(fp(10%p,r/a[i],p)==1)r/=a[i];
}
cout<<solve(n,m,r)<<endl;
}
}