zoukankan      html  css  js  c++  java
  • [CodeForces][数学][组合][快速幂] CF327C Magic Five

    题面

    首先可以想到 (5) 的倍数一定以 (5)(0) 结尾,也就是我们选择的一段数字,只要保证结尾为 (0)(5),前面数字是什么是无关答案,可以任选的。、
    那么我们就先考虑在 a 这个串中如何统计答案,最后将 (k) 个串平起来的答案直接乘上去就好了。

    对于字符串 a,记最高位为第 (0) 位,最低位为第 (n-1) 位,根据乘法及加法原理,有:

    [ans_a = 2^0 imes (a_0 == 5 || a_0 == 0) + 2^1 imes (a_1 == 5 || a_1 == 0) + cdots + 2^{n-1} imes (a_{n-1} == 5 || a_{n-1} == 0) ]

    那么我们对于 (k)a,有这样的方案:

    [ans_1 = ans_a imes (2^n)^0 \ ans_2 = ans_a imes (2^n)^1 \ ans_3 = ans_a imes (2^n)^2 \ cdots \ ans_k = ans_a imes (2^n)^{k-1} ]

    对答案求一下和,发现其实就是等比数列求和,得到以下结果:

    [ANS = ans_1 imes frac{2^{nk}-1}{2^n-1} ]

    其中 (n) 为字符串长度。
    于是这道题只剩下轻松愉快的快速幂和费马小定理求逆元了。

    代码:

    // 只要保证最后一位是 0 或 1,就能被 5 整除
    // 所以答案是每一个 5 或非前导 0 之前的部分求方案
    // s 不需要显式的建出来,每一个串对应多更新答案
    // 前导 0 计算在结果中
    
    # include <iostream>
    # include <cstdio>
    # include <string>
    
    const long long MOD = 1e9+7;
    
    long long QPow(long long x, long long y){
    	long long ans = 1, base = x%MOD;
    	while(y){
    		if(y & 1){
    			ans = (ans * base) % MOD;
    		}
    		base = (base * base) % MOD;
    		y >>= 1;
    	}
    	return ans;
    }
    
    long long Inv(long long x){
    	return QPow(x, MOD-2);
    }
    
    int main(){
    	std::string a; int k;
    
    	std::cin>>a>>k;
    
    	long long ans = 0;
    	for(int i = 0; i <= a.length()-1; i++){
    		if(a[i] == '0' || a[i] == '5'){
    			ans = (ans + QPow(2, i)) % MOD;
    		}
    	}
    
    	printf("%lld", (((ans * (QPow(2, 1ll*a.length()*k) - 1)) % MOD) * Inv(QPow(2, a.length())-1)) % MOD);
    
    	return 0;
    }
    
  • 相关阅读:
    常量
    语音合成技术(深度学习方法简介)
    在 Linux 上如何清除内存的 Cache、Buffer 和交换空间
    Bash Bang (!) commands(bash的“!”命令,重新运行前一个命令的全部或部分。)
    Ubuntu apt pip conda 代理设置
    rsync 远程数据同步
    设置 jupyter notebook 可远程访问
    ubuntu 挂载硬盘(GPT分区,大于2T的硬盘)
    用树结构构造一篇文章(待完成)
    数组切分(句子拼接)
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/13726429.html
Copyright © 2011-2022 走看看