这题的关键还是如何求等比数列之和。
对于这道题即求等比数列 p*(x + x^2 + ...+ x^k),其中p是单个字符串可能的个数,x是2^len (len是单个字符串的长度)。
方法一:
求sum=x^1+x^2+x^3+x^4+x^5+x^6+x^7 ....... x^t
共有t项
公式:
若t%2==0 sum(t)=sum(t/2)+sum(t/2)*2^(t/2);
若t%2==1 sum(t)=sum(t/2)+sum(t/2)*2^(t/2)+ x^t;
方法二:
对于(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
如果b'是b的逆元..那么b'*b % p==1...而又b*b^(p-2)%p==b^(p-1)%p==1 所以b的逆元b'=b^(p-2)%p
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <map>
#define mod 1000000007
using namespace std;
typedef long long ll;
const int maxn = 100005;
char a[maxn];
ll p,len;
ll Pow(ll x,ll y){//快速幂x^y
ll ans = 1;
for(;y;y >>= 1){
if(y&1){
ans *= x;
ans %= mod;
}
x *= x;
x %= mod;
}
return ans;
}
//方法一:
//ll sum(ll x,ll k){//求等比数列 p*(x + x^2 + ...+ x^k),其中p是单个字符串可能的个数,x是2^len (len是单个字符串的长度)。
// if(k == 1) return p;
// ll ans = sum(x,k>>1);
// ans = (ans*(1 + Pow(x,k>>1)))%mod;
// if(k&1)
// ans = (ans + p*Pow(x,k-1))%mod;
// return ans;
//}
//方法二:
ll sum(ll x,ll k){//求等比数列 p*(x + x^2 + ...+ x^k) 利用等比数列前n项和,费马小定理和乘法逆元,求出x-1的逆元temp
ll ans;
ll temp = Pow(x-1, mod-2);
ans = (p*(Pow(x,k)-1))%mod;
return (ans*temp)%mod;
}
int main(){
int k;
while(cin>>a){
cin>>k;
len = (int)strlen(a);
p = 0;
ll temp = 1;
for(int i = 0;i < len;i++){//算出单个字符串可能的个数
if(a[i] == '0' || a[i] == '5')
p = (p+temp)%mod;
temp = (temp*2)%mod;
}
//printf("p = %lld\n",p);
cout<<sum(Pow(2, len),k)<<endl;
}
return 0;
}