Codeforces 327C 快速幂+等比数列求和+乘法逆元

原创 2018年04月16日 22:01:34

题目链接:http://codeforces.com/problemset/problem/327/C
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 = |a|·k.

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

题意

有一个循环了n次字符串a,a中的字符均为数字。
现在要删去其中的若干字符(不能全删),使得最后剩下的数字是5的倍数。

思路

先说一个基本但必须用到的结论:若一个数是5的倍数,则它末位是5的倍数(即为5或0)。
设这个字符串为a[1]a[2]a[3]...a[p]...a[n]。
首先需要思考一个问题:以a[p]结尾的数有多少个。
答案是:2^(p-1)。
这个的推导过程很简单,这里就不赘述了。
并注意:数据过大,需要快速幂。

然后要想一个问题:由于循环次数n过大,从前到后枚举一次不现实,需要用数学方法简化。
由于它循环n次每次都是相同的字符串,所以易得
以a[p]结尾的数个数+以a[p+len]结尾的数个数+...+a[p+len*(n-1)]
=2^(p-1)+2^(p+len-1)+...+2^(p+len*(n-1)-1)
=2^(p-1)*[2^0+2^len+...+2^(len*(n-1))]
然后用等比数列求和公式化简,得
原式=2^(p-1)*(2^(len*n)-1/2^len-1)。

现在又面临一个更大的问题:
结果需要对10^9+7取模,但是在上式分母上下都是快速幂,取模后会有精度丢失的问题。
所以需要引进乘法逆元来完成。

乘法逆元的定义是:如果ab≡1 (modp),则说b是mod p意义下的乘法逆元。
在此题中,需要求(a/b)%p的值,则设k是b的乘法逆元,则(a/b)%p=(a*k)%p。
这个等式的证明可以看这篇题解:
http://www.cnblogs.com/tiankonguse/archive/2012/08/14/2638949.html
而求b的乘法逆元可以运用费马小定理:
由b^(p-1)≡1 (modp),得b的乘法逆元是b^(p-2)。
所以问题就解决了。

PS.变量最好用long long,如果一个int和一个long long相乘可能会出错。

代码

#include<stdio.h>
#include<cstring>
using namespace std;
const long long mod=1000000007;
long long fastpow(long long b,long long p,long long k) {
    b%=k;
    long long ret=1;
    while(p) {
        if(p&1) ret=(ret%k)*(b%k)%k;
        p>>=1;
        b=(b%k)*(b%k)%k;
    }
    return ret%mod;
}
char a[1000001];
int main() {
//  freopen("data.txt","r",stdin);
    long long k,len;
    gets(a);
    scanf("%I64d",&k);
    len=strlen(a);
    long long ans=0;
    for(int i=0; i<len; i++) {
        if(a[i]=='5' || a[i]=='0') {
            ans=(ans+fastpow(2,i,mod))%mod;
        }
    }
    long long tmp=fastpow(2,len,mod)%mod;
    long long p=fastpow(2,len*k,mod)%mod;
    tmp=((1-tmp)%mod+mod)%mod;
    tmp=fastpow(tmp,mod-2,mod);
    p=((1-p)%mod+mod)%mod;
    ans=(ans*p)%mod*tmp%mod;
//  if(a[0]=='8' && a[1]=='4')  printf("%I64d %I64d ",tmp,p);
    printf("%I64d",ans);
    return 0;
}
/*
27755776656210607832788619414635535178188775623838313967013958143619017005079991285469853503718562504927535176713879737569375166451462839457844835806559098448980069427607
151
*/

codeforces-327C Magic Five(等比数列求和+快速幂+逆元)

点击打开题目链接 题意:给出一个字符串a和一个整数k,表示这个字符串s是由k个 a连接得到的,要求任意删除字符串s中的任意位上的字符,使得删除后的字符串表示的数能被5整除。题目说明所求结果可能包含前导...
  • CHeck_Check_check
  • CHeck_Check_check
  • 2016-07-18 23:02:53
  • 359

等比数列求和快速幂

CF-678D 看求的和(a^n-1)/(a-1)按奇偶递推 #include using namespace std; const long long m=1e9+7; ...
  • sinat_33397705
  • sinat_33397705
  • 2016-06-14 14:06:49
  • 202

CodeForces 327C Magic Five 题解&代码

其实挺水的?【并不 反正代码不长思路: 对于一个串,我们很容易知道对于某一位i是0或5,有2^i种选法【字符串从第0位开始,第i位确定】 一个串的选法也很容易求出,按顺序求出每一位的选法,加起来...
  • Rainbow6174
  • Rainbow6174
  • 2016-01-19 21:32:14
  • 567

Codeforces 327C 乘法逆元 + 费马小定理 || 等比数列二分求和取模

C. Magic Five time limit per test 1 second memory limit per test 256 megabytes input standard inp...
  • Triose_Stream
  • Triose_Stream
  • 2016-08-01 10:25:04
  • 385

等比数列求和(C++实现)

第一种实现方式,最传统古老的,先求出每一项,然后再求和。#include #include using namespace std; int main(int argc, char* argv[]...
  • a1b2c3d4123456
  • a1b2c3d4123456
  • 2015-12-25 17:26:58
  • 2192

模板:快速幂和快速等比数列和

快速幂和快速等比数列和 其中没用使用乘法逆元。。但是乘法逆元的更加快速,如果moddd数不是一个素数并且不好求他的欧拉函数,就可以使用等比数列的二分性。。。 但是速度比较慢、、 const in...
  • lovewangtaotao
  • lovewangtaotao
  • 2016-08-12 19:09:22
  • 143

等差、等比数列的求和公式

等差数列和公式 Sn=n(a1+an)/2=na1+n(n-1)/2 d 等比数列求和公式 q≠1时 Sn=a1(1-q^n)/(1-q)=(a1-anq)/(1-q) q=1时Sn=na1 (a1为...
  • kwame211
  • kwame211
  • 2017-12-01 14:39:16
  • 585

POJ-1845-Sumdiv 等比数列求和/数学/(二分法/逆元法/变换取模法)

题意:输入a,b,求a^b的所有因子之和 http://poj.org/problem?id=1845 分解a的质因数a=p1^t1*p2^t1........ 每个质因数对sum的贡献...
  • viphong
  • viphong
  • 2016-02-19 23:42:08
  • 694

等比数列求和推导及优化

等比数列求和推导及优化
  • CHNWJD
  • CHNWJD
  • 2017-03-03 09:18:19
  • 469
收藏助手
不良信息举报
您举报文章:Codeforces 327C 快速幂+等比数列求和+乘法逆元
举报原因:
原因补充:

(最多只允许输入30个字)