Codeforces 1027G X-mouse in the Campus

(Codeforces 1027G) (Codeforces 1027G) 考虑两个整数 1m,n1014,(m,n)=1, 1 ⩽ m , n ⩽ 10 14 , ( m , n ) = 1 , 问若定义等价类 x¯¯¯={a|amk=x,aZn} x ¯ = { a | a m k = x , a ∈ Z n } ,这样的等价类有多少个?
M=m,n M = ⟨ m , ⋅ n ⟩ ,由欧拉定理 mφ(n)1 m φ ( n ) ≡ 1 (m,n)=1, ( m , n ) = 1 , 这是一个 φ(n) φ ( n ) 阶循环群.
那么 x¯¯¯=xM x ¯ = x M ,容易由此知道 φ(n)=ci|x¯¯¯i| φ ( n ) = c i | x ¯ i | ,所有不同的 x¯¯¯ x ¯ 就是答案。
但是直接计算等价类的复杂度是 O(n) O ( n ) ,那就 TLE TLE 了.
于是考虑一个加速:对于任意 aZn,(amk,n)=(a,n) a ∈ Z n , ( a m k , n ) = ( a , n ) ,所以记 φ(n/d)=k=1n[(k,n)=d] φ ( n / d ) = ∑ k = 1 n [ ( k , n ) = d ] ,答案就是 d|nφ(n/d)|d¯¯¯| ∑ d | n φ ( n / d ) | d ¯ | .
现在问题来了. |d¯¯¯| | d ¯ | 如何计算?
min k:dxkd(modn),dd=ndxkd+dd(modn)xk1(modnd) min k : d x k ≡ d ( mod n ) , d d ′ = n ⇔ d x k ≡ d + d d ′ ( mod n ) ⇔ x k ≡ 1 ( mod n d )
注意到 k|φ(d)|φ(n) k | φ ( d ) | φ ( n ) ,于是求 φ(n) φ ( n ) 的素因子然后枚举即可…

#include 
#include 
#include 
#include 
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));
}

你可能感兴趣的:(codeforces,数论,codeforces,数论)