版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Myriad_Dreamin/article/details/82503489
考虑两个整数
问若定义等价类
,这样的等价类有多少个?
记
,由欧拉定理
且
这是一个
阶循环群.
那么
,容易由此知道
,所有不同的
就是答案。
但是直接计算等价类的复杂度是
,那就
了.
于是考虑一个加速:对于任意
,所以记
,答案就是
.
现在问题来了.
如何计算?
注意到
,于是求
的素因子然后枚举即可…
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
inline long long mul(long long a,long long b,long long c){
long long res=(a*b-(long long)((double)a*b/c+0.1)*c)%c;
return res<0?res+c:res;
}
inline long long qp(long long a,long long b,long long mod){
a%=mod;long long tmp=a,res=1;
while(b){
if(b&1)res=mul(res,tmp,mod);
tmp=mul(tmp,tmp,mod); b>>=1;
}
return res;
}
long long m,sqrtm,x,factor[200],fact[100000],f[100000],prim[100000];
int n=0,ptop=0,tol=0;
inline void calfact(long long m){
for(long long i=1,mi;i<=sqrtm;i++){
mi=m/i;
if(i*mi==m){
if(i!=mi)fact[++n]=mi;
fact[++n]=i;
}
}
sort(fact+1,fact+1+n);
}
inline void calprim(long long m,long long *prim,int &ptop){
for(long long i=2;i<=sqrtm;i++){
if(m%i==0){
prim[++ptop]=i;
while(m%i==0)m/=i;
}
}
if(m>1)prim[++ptop]=m;
return ;
}
inline long long Euler(long long n){
long long phi=n;
for(int i=1;i<=ptop;i++){
if(phi%prim[i]==0)phi-=phi/prim[i];
}
return phi;
}
inline long long cal(long long m){
long long res=0,tmpres,trueres,Eulerm=Euler(m);
if(Eulerm>1)calprim(Eulerm,factor,tol);else factor[++tol]=1;
for(int i=1;i<=n;i++){
tmpres=trueres=Euler(fact[i]);
if(tmpres>1){
for(int j=1;j<=tol;j++){
while(tmpres%factor[j]==0&&
qp(x,tmpres/factor[j],fact[i])==1)tmpres/=factor[j];
}
}
res+=trueres/tmpres;
}
return res;
}
int main(){
scanf("%I64d%I64d",&m,&x);
sqrtm=sqrt(m+1);
calfact(m);
calprim(m,prim,ptop);
printf("%I64d\n",cal(m));
}