2019牛客暑期多校D.Big Integer

题面

题意:

定义\(A(n)\)\(n\)个1构成的数字,如\(A(3)=111\),计算有多少对\((i,j)\)使得\(A(i^j) \% p = 0\)

思路:

通过枚举发现是有上面的等式是有循环节的,而且循环节是\(p-1\)的因子,因此暴力枚举计算出循环节\(d\),接下来就是求有多少对\(i^j \% d=0\)
\(d\)进行质因子分解,得
\[ d={p_1}^{q_1} \cdot {p_2}^{q_2} \cdot {p_3}^{q_3} ...{p_k}^{q_k} \]

那么要使\(i^j \%d = 0\),则\(i\)必须为
\[ g={p_1}^{\lceil {\frac{q_1}{j}} \rceil} \cdot {p_2}^{\lceil {\frac{q_2}{j}} \rceil} \cdot {p_3}^{\lceil {\frac{q_3}{j}} \rceil} ...{p_k}^{\lceil {\frac{q_k}{j}} \rceil} \]
的倍数。因此一共有\(\frac{n}{g}\)个合法的\(i\)
由于\(q_i \leq 30\),因此\(j\)\(30\)之后和\(30\)的答案相同,因此\(j\)只需要枚举到\([1,30]\),分别计算出\(g\)的值。

代码:

#include<bits/stdc++.h>
 
using namespace std;
long long qpow(long long a,long long b,long long mod){
    long long ans=1;
    while(b){
        if(b&1) ans=(ans%mod*a%mod)%mod;
        a=(a%mod*a%mod)%mod;
        b>>=1;
    }
    return ans%mod;
}
long long qp(long long a,long long b){
    long long ans=1;
    while(b){
        if(b&1) ans=(ans*a);
        a=(a*a);
        b>>=1;
    }
    return ans;
}
int main(){
    int T;
    //freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--){
        long long ans=0;
        long long p,n,m;
        vector<long long> pr;
        long long re;
        scanf("%lld %lld %lld",&p,&n,&m);
        if(p==2||p==5){
            puts("0");
            continue;
        }
        if(p==3){
            cout<<n/3*m<<endl;
            continue;
        }
        vector<long long> all;
        for(int i=2;i*i<=p-1;i++){
            if((p-1)%i==0){
                if(i*i==p-1) all.push_back(i);
                else{
                    all.push_back(i);
                    all.push_back((p-1)/i);
                }
            }
        }
        all.push_back(p-1);
        long long id;//循环节
        sort(all.begin(),all.end());
        for(auto v:all){//找到循环节
            if((qpow(10,v,p))%p==1){
                id=v;break;
            }
        }
        vector<long long> nums;
        for(int i=2;i*i<=id;i++){//质因子分解
            if(id%i==0){
                 int num=0;
                pr.push_back(i);
                while(id%i==0){
                     id/=i;
                     num++;
                }
                nums.push_back(num);
            }  
        }
        if(id!=1){
             pr.push_back(id);
             nums.push_back(1);
        }
        long long g;
        for(long long j=1;j<=min((long long)m,(long long)30);j++){
            g=1;
            for(int i=0;i<(int)nums.size();i++){
                g*=qp(pr[i],(nums[i]+j-1)/j);
            }
            if(j==30) ans+=(n/g)*(m-29);
            else ans+=n/g;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/codancer/p/12232403.html