CF 327C 数学题 等比公式

来源:互联网 发布:什么是云计算技术 编辑:程序博客网 时间:2024/05/16 01:31
C. Magic Five
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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 by5. Note that, the resulting number may contain leading zeros.

Now Iahub wants to count the number of ways he can obtain magic number, modulo1000000007 (109 + 7). Two ways are different, if the set of deleted positions ins differs.

Look at the input part of the statement, s is given in a special form.

Input

In the first line you're given a string a (1 ≤ |a| ≤ 105), containing digits only. In the second line you're given an integerk (1 ≤ k ≤ 109). The plates is formed by concatenating k copies of a together. That isn = |ak.

Output

Print a single integer — the required number of ways modulo 1000000007 (109 + 7).

Sample test(s)
Input
12561
Output
4
Input
139902
Output
528
Input
5552
Output
63
Note

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 are26 - 1 = 63 possible ways to delete digits.


题解
原题转化为  ans=a1 *(q^n-1)/(q-1) ,n == k

a1的值就是一个字符串中 0,5的位置。左边开始从0计数。 则依次计为 i0,i1,i2,i3..  a1 = 2^i0+2^i1+2^i2+2^i3 ...

其中q=2^strlen(s).

而难点是数太大了。。mod 运算比较麻烦。。

q^n此类用快速乘法幂解出答案。唯一剩下的就是  (c/d) mod q 时怎么计算。

我用的是模P乘法逆元
 对于整数a、p,如果存在整数b,满足ab mod p =1,则说,b是a的模p乘法逆元。
 定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1   

令(p*b)%mod=1,则有以下成立
对于(a/b)%mod= (a/b)*(p*b)%mod=(a*p)%mod=c

而对于(p*b)%mod=1,有 (p*b)%mod=1 <==> p*b-(p*b)/mod*mod=1
将 p用X代替,p*b/mod用Y代替,b用A表示,mod用B表示. 化成了AX+BY=1;
//#define ll long long
//inline ll extend_gcd(ll A,ll B,ll &X,ll &Y);
因此调用extend_gcd(b,mod,X,Y)即可解出答案X,即p,即逆元.

综上所以只用求出q-1的逆元即可。

代码:

/* * @author ipqhjjybj * @date  20130704 * */#include <cstdio>#include <cstring>#include <iostream>#define clr(x,k) memset((x),(k),sizeof(x))#define MAX(a,b) ((a)>(b)?(a):(b))#define MAXN 10000001#define ll long long#define MOD 1000000007using namespace std;char s[100004];int k;//求逆元//欧几里得扩展//对(p*b)%mod=1//调用extend_gcd(b,mod,X,Y),X即为p的解inline ll extend_gcd(ll a,ll b,ll &x,ll &y){    ll ans,t;    if(b==0){x=1,y=0;return a;}    ans=extend_gcd(b,a%b,x,y);t=x,x=y,y=t-(a/b)*y;    return ans;}ll multipow(ll base,ll n){    ll r=1;    while(n){        if(n&1)            r=(r*base)%MOD;        base = (base*base)%MOD;        n>>=1;    }    return r;}int main(){    while(scanf("%s %d",s,&k)!=EOF){        ll a1=0;        int len=strlen(s);        for(int i=0;i<len;i++){            if(s[i]=='0'||s[i]=='5'){                    a1=(a1+multipow(2,i))%MOD;            }        }        ll q = multipow(2,len);        ll q1 = (q+MOD-1)%MOD;        ll X,Y;        extend_gcd(q1,MOD,X,Y);        X = (X+MOD)%MOD;//防止X为负数        ll qn_x = (multipow(q,k)-1)*X%MOD;        ll ans = (a1*qn_x)%MOD;        cout<<ans<<endl;    }    return 0;}

后来发现。如果把所有的i值全部提取出来。统一进行调用函数multipow。性能提升比较明显。。能从62MS降到42MS;

原创粉丝点击