CodeForces327C

来源:互联网 发布:希尔巴布尔美全灭mac 编辑:程序博客网 时间:2024/05/21 15:39

这是今天做的一道快速幂的题,看完题目之后用笔在草稿纸上写写就能分析出来其中的数学公式 ans=(Σpow(2,i)*(pow(2,k*len)-1)/(pow(2,len)-1))%M  但是代码交上去之后一直WA,总是不明白哪里错了,WA了快十次实在不知道怎么改了,于是上网搜了下题解,发现了新大陆!!


在刚才写的公式里面有一个除法求模的运算,之前的代码我就直接相除取模了

ans=(ans+foo(2,i)*((Pkl-1)/(Pl-1)))%M;

实则是不可取的,因为(a/b)%M 并不会等于(a%M)/(b%M)%M

在我看的题解的分析中有说到关于求除法模运算的方法,但是简单带过了,只知道是叫  乘法逆元  于是我就搜索乘法逆元啊,找到了两篇博客:

一篇是数学证明:http://www.cnblogs.com/tiankonguse/archive/2012/08/14/2638949.html


另一篇是求乘法逆元的方法:http://sujinyue.is-programmer.com/posts/38179.html


(这是博客原文,地址在上面,博主若是不希望被转载通知立删)


看了几遍之后大概了解了其中的思路,然后自己验证了一下题目中给定的M=1000000007是素数,那么快速幂求pow(pl,M-2)就可以了,方便简洁。这个方法对快速幂的题目算是升华吧,再也不怕除法模了。


下面是题目代码:

#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<string>#include<iostream>using namespace std;long long M=1000000007;char s[100];long long foo(long long a,long long b){   // printf("pow(%lld,%lld)=",a,b);    long long ans=1;    a=a%M;    while(b)    {        if(b%2) ans=(ans*a)%M;        b/=2;        a=(a*a)%M;    }  //  printf("%lld ",ans);    return ans;}int main(){  //  freopen("in.txt","r",stdin);    long long ans;    while(scanf("%s",s)!=EOF)    {        long long len;        len=strlen(s);        if(s[0]=='-')        {            for(int i=1;i<len;++i)                s[i-1]=s[i];            --len;        }        long long k;        scanf("%lld",&k);        long long Pl;        Pl=foo(2,len);        long long Pkl;        Pkl=foo(Pl,k);        ans=0;        for(long long i=0;i<len;++i)        {            if(s[i]=='0'||s[i]=='5')            {                ans=(ans+foo(2,i)*((Pkl-1)/(Pl-1)))%M;            }        }        printf("%lld\n",ans);    }    return 0;}

0 0
原创粉丝点击