• CF327C 快速幂,费马小定理


    链接:http://codeforces.com/problemset/problem/327/C

    题意:给一串数,这串数重复k次,求去掉一些数后得到的新数能被5整除,问有多少种方法得到满足条件的数。

    思路:要求能被5整除,则数的末位必然是0或5,求出原始串中0和5的位置,从0开始计数,位置为i1,i2,i3,,,in,则有a=2^i1+2^i2+...+2^in种方法。则在所有中的方法总数为:s=a*(q^n-1)/(q-1),q=2^len,len为原始串的长度。这个公式推一下就出来了。由于数据范围很大,所以要模1e9+7。在求幂的时候采用的是快速幂来做。除以(q-1)的话,求出它的逆元。由欧拉定理,(a,n)=1,a^phi(n)=1(mod n),a的逆为a^(phi(n)-1),n为素数时,phi(n)=n-1,所以a的逆为a^(n-2)%n.

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    typedef long long LL;
    char a[100002];
    int k;
    int mod=1e9+7;
    
    //LL fastmi(LL a, LL n)
    //{
    //    if (n == 0)
    //        return 1;
    //    else if (n % 2 == 1)
    //        return (a * fastmi(a, n - 1)) % mod;
    //    else
    //    {
    //        LL temp = fastmi(a, n / 2);
    //        return (temp * temp) % mod;
    //    }
    //}
    LL fastmi(LL a, LL b) {
        LL ans=1;
        while (b) {
            if (b&1){ans = (ans*a)%mod; b--;}
            b/=2; a = a * a % mod;
        }
        return ans;
    }//由78s降到了46s
    int main() { scanf("%s",a); scanf("%d",&k); int len=strlen(a); LL ans=0; for(int i=0; i<len; i++) if(a[i]=='0' || a[i]=='5') { ans=(ans+fastmi(2,i))%mod; } LL q=fastmi(2,len); LL p=fastmi(q,k)%mod; p=(p-1+mod)%mod; LL q1=(q-1+mod)%mod; ans=(ans*p)%mod; q1=fastmi(q1,mod-2)%mod;//欧拉定理 ans=(ans*q1)%mod; printf("%I64d ",ans); return 0; }

    一开始不知道欧拉定理,公式也没化简,用循环直接求,自然T了。公式的话,能化简就化简,化简了可以看出一些东西来。

    究竟是我抛弃了历史,还是历史遗弃了我。
  • 相关阅读:
    思考题13-1.b
    算法导论 第三版 9.3-8
    算法导论第三版思考题8-4
    算法导论第三版思考题8-3.b
    算法导论第三版思考题8-3.a
    算法导论第三版思考题8-2.e
    算法导论 第三版 思考题 7-4
    test
    一个朋友面试时遇到的算法题(怎么组合后得到最大整数)
    监听器模式、观察者模式
  • 原文地址:https://www.cnblogs.com/54zyq/p/3201224.html
Copyright © 2020-2023  润新知