CF 327C 数学题 等比公式

73 篇文章 21 订阅
18 篇文章 0 订阅
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 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.

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 integer k (1 ≤ k ≤ 109). The plate s is formed by concatenating k copies of a together. That is n = |ak.

Output

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

Sample test(s)
Input
1256
1
Output
4
Input
13990
2
Output
528
Input
555
2
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 are 26 - 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 1000000007
using 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;

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值