Codeforces Round #191 (Div. 2) C. Magic Five

       这题的关键还是如何求等比数列之和。

   对于这道题即求等比数列 p*(x + x^2 + ...+ x^k),其中p是单个字符串可能的个数,x2^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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值