zoukankan      html  css  js  c++  java
  • 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了。公式的话,能化简就化简,化简了可以看出一些东西来。

    究竟是我抛弃了历史,还是历史遗弃了我。
  • 相关阅读:
    c#语音报时(含完整的声音资源文件).rar
    SQL 查看数据库表的容量大小
    c# 鼠标在控件上拖动 移动窗体 移动窗口
    C# winform 右下角弹出窗口结果
    Qt通用方法及类库8
    Qt通用方法及类库7
    Qt通用方法及类库6
    Qt通用方法及类库5
    Qt通用方法及类库4
    Qt通用方法及类库3
  • 原文地址:https://www.cnblogs.com/54zyq/p/3201224.html
Copyright © 2011-2022 走看看