CodeForces Round #191 (327C) - Magic Five 乘法逆元与费马小定理

 

CodeForces Round #191 (327C) - Magic Five 乘法逆元与费马小定理

分类: 数论   229人阅读  评论(0)  收藏  举报

    这题的关键还是如何求等比数列之和,之前使用的二分求和...这里用数论的知识直接解决...

    对于(a/b)%c这类运算不能等价于(a%c / b%c)...但是可以等价为(a*b')%c...其中b'为b的逆元..

    而(a*b')%c这类运算可以拆解为(a%c * b%c)..

    那么关键就是求c的逆元了.. 值得留意的是10000007是一个质数...

    根据费马小定理对于任意的质数p有任意的正整数a满足a^(p-1)%p==1

    如果A是a的逆元..那么A*a % p==1...而又a*a^(p-2)%p==a^(p-1)%p==1   所以a的逆元A=a^(p-2)%p

    剩下的就简单了..


Program:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<stdio.h>  
  3. #include<string.h>  
  4. #include<set>  
  5. #include<algorithm>  
  6. #include<cmath>  
  7. #define oo 1000000007  
  8. #define ll long long  
  9. #define pi acos(-1.0)  
  10. #define MAXN 505  
  11. using namespace std;     
  12. char s[100004];  
  13. ll len;   
  14. ll POW(ll a,ll k)  
  15. {  
  16.       ll x,ans=1;  
  17.       x=a;  
  18.       while (k)  
  19.       {  
  20.            if (k%2) ans=(ans*x)%oo;  
  21.            x=(x*x)%oo;  
  22.            k/=2;  
  23.       }  
  24.       return ans;  
  25. }  
  26. ll T(ll n,ll t)  
  27. {  
  28.       ll ans,x=POW(POW(2,len)-1,oo-2);  
  29.       ans=(t*POW(POW(2,len),n)-t)%oo;  
  30.       return (ans*x)%oo;  
  31. }  
  32. int main()  
  33. {   
  34.       int k,i;  
  35.       ll ans,x,l;    
  36.       while (~scanf("%s",s))  
  37.       {  
  38.              scanf("%d",&k);  
  39.              len=strlen(s);  
  40.              ans=0;  
  41.              x=1;  
  42.              for (i=0;i<len;i++)  
  43.              {  
  44.                    if (s[i]=='0' || s[i]=='5')  
  45.                        ans=(ans+x)%oo;  // 不要每次都做..加起来  
  46.                    x=(x*2)%oo;  
  47.              }  
  48.              ans=T(k,ans);  // 只做一次  
  49.              printf("%I64d\n",ans);  
  50.       }  
  51.       return 0;  
  52. }  

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