CodeForces Round #191 (327C) - Magic Five 等比数列求和的快速幂取模

很久以前做过此类问题..就因为太久了..这题想了很久想不出..卡在推出等比的求和公式,有除法运算,无法快速幂取模...

看到了

http://blog.csdn.net/yangshuolll/article/details/9247759

才想起等比数列的快速幂取模....

求等比为k的等比数列之和T[n]..当n为偶数..T[n] = T[n/2] + pow(k,n/2) * T[n/2]

                                                          n为奇数...T[n] = T[n/2] + pow(k,n/2) * T[n/2] + 等比数列第n个数的值

    比如 1+2+4+8 = (1+2) + 4*(1+2) 

             1+2+4+8+16 = (1+2) + 4*(1+2) + 16 


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 m;

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)

{

      if (n==1) return t;

      ll data=T(n/2,t);

      data=(data+data*POW(m,n/2))%oo;

      if (n%2) data=(data+POW(m,(n-1))*t)%oo;

      return data;

}

int main()

{ 

      int k,i;

      ll ans,x,len; 

      while (~scanf("%s",s))

      {

             scanf("%d",&k);

             len=strlen(s);

             m=POW(2,len);

             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)