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

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

    对于(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:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 505
using namespace std;   
char s[100004];
ll len; 
ll POW(ll a,ll k)
{
      ll x,ans=1;
      x=a;
      while (k)
      {
           if (k%2) ans=(ans*x)%oo;
           x=(x*x)%oo;
           k/=2;
      }
      return ans;
}
ll T(ll n,ll t)
{
      ll ans,x=POW(POW(2,len)-1,oo-2);
      ans=(t*POW(POW(2,len),n)-t)%oo;
      return (ans*x)%oo;
}
int main()
{ 
      int k,i;
      ll ans,x,l;  
      while (~scanf("%s",s))
      {
             scanf("%d",&k);
             len=strlen(s);
             ans=0;
             x=1;
             for (i=0;i<len;i++)
             {
                   if (s[i]=='0' || s[i]=='5')
                       ans=(ans+x)%oo;  // 不要每次都做..加起来
                   x=(x*2)%oo;
             }
             ans=T(k,ans);  // 只做一次
             printf("%I64d\n",ans);
      }
      return 0;
}


你可能感兴趣的:(CodeForces Round #191 (327C) - Magic Five 乘法逆元与费马小定理)