There is a long plate s containing n digits. Iahub wants to delete some digits (possibly none, but he is not allowed to delete all the digits) to form his "magic number" on the plate, a number that is divisible by 5. Note that, the resulting number may contain leading zeros.
Now Iahub wants to count the number of ways he can obtain magic number, modulo 1000000007 (109 + 7). Two ways are different, if the set of deleted positions in s differs.
Look at the input part of the statement, s is given in a special form.
In the first line you're given a string a (1 ≤ |a| ≤ 105), containing digits only. In the second line you're given an integer k (1 ≤ k ≤ 109). The plate s is formed by concatenating k copies of a together. That is n = |a|·k.
Print a single integer — the required number of ways modulo 1000000007 (109 + 7).
1256 1
4
13990 2
528
555 2
63
In the first case, there are four possible ways to make a number that is divisible by 5: 5, 15, 25 and 125.
In the second case, remember to concatenate the copies of a. The actual plate is 1399013990.
In the third case, except deleting all digits, any choice will do. Therefore there are 26 - 1 = 63 possible ways to delete digits.
题意:给你n个同样的字符串,你在里面任意删除数字,使剩下的数字刚好能被5整除(数字前缀可以为0)。
思路:一个数要被5整除,那么它的末尾只能是5或0。如13090,它的长度len=5,假设有n个这个样的串;
那么先分析体格串的删法:
如果以中间的0为末尾,那么后面的都是要删去的,但是中间那个0前面的1和3可删可不删,此时有2^2种;
如果以后面的的0为末尾,那么前面的四个数都可删可不删,此时总共有2^4种;
那么一个这样的串总的删法有2^2+2^4种。
现在再看130901309013090,它的长度Len=5*3:
它总共有2^2+2^4+2^7+2^9+2^12+2^14=(2^2+2^4) + 2^5*(2^2+2^4) + (2^5)^2*(2^2+2^4).
那么现在看出它是有规律的,等比数列求和,我们发现以一串字符的结果为首项,以2^len为公比的n项等比数列求和。
a1*(2^(len*n)-1) / (2^len-1)就是我们所求的答案;那么现在问题又来了,题目的数据特别大,不能这样直接算,我们采取快速幂,当然要对1e9+7取模,我们再次用到费马小定理(a^(-1)%P=a^(P-2)%P,这样处理一下分母,转化为乘法逆元,然后直接乘起来就好。
AC代码:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-10;
const double PI=acos(-1.0);
const int maxn=100009;
const int mod=1e9+7;
char s[maxn];
LL a[maxn];
LL n;
LL quickpow(LL n,LL m)
{
LL tmp=1;
while(m>0)
{
if(m&1)
tmp=(tmp*n)%mod;
n=(n*n)%mod;
m>>=1;
}
return tmp;
}
LL Fm(LL x)//费马小定理
{
return quickpow(x,mod-2)%mod;
}
int main()
{
while(~scanf("%s%lld",s,&n))
{
int cnt=0;
LL ans=0;
LL len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='0'||s[i]=='5')
ans=(ans+quickpow(2,i))%mod;
}
LL q=(Fm(quickpow(2,len)-1))%mod;
LL tmp=(quickpow(2,len*n)-1)%mod;
ans=(ans*tmp%mod)*q%mod;//这里一定要边乘边取模,后面数据会特别大
printf("%lld\n",ans);
}
return 0;
}