[题解]CF327C Magic Five
思路
首先考虑非常暴力的方法,令 \(s_i\) 表示这个数字的第 \(i\) 位上的数。则对于一个 \(s_i = 0/5\),则考虑将其留下成为最后一位元素:\(i\) 之后的所有元素都必须删,并且在 \(i\) 之前的元素可删可不删,因此贡献是 \(2^{i - 1}\)。得到如下表达式:
\[
\sum 2^{i - 1} [s_i = 0/5]
\]
但是你发现每一次循环的情况是已知的,发现如果 \(s_i = 0/5\) 则 \(s_{i + n} = 0/5\)。因此你考虑计算每一位的对应位分开算,即:
\[
\sum_{i = 1}^{n}(2^{i - 1} + 2^{i + n - 1} + \dots 2^{i + (k - 1)n - 1})[s_i = 0/1]
\]
然后你发现中间那一个式子是一个公比为 \(2^n\) 的等比数列,直接算即可:
\[
\sum_{i = 1}^{n}(2^{i - 1}\frac{2^{n^k} - 1}{2^n - 1})[s_i = 0/1]
\]
Code
#include <bits/stdc++.h>
#define re register
#define int long long
#define Add(a,b) (((a) % mod + (b) % mod) % mod)
#define Sub(a,b) ((((a) % mod - (b) % mod) % mod + mod) % mod)
#define Mul(a,b) (((a) % mod) * ((b) % mod) % mod)
using namespace std;
const int N = 1e5 + 10,mod = 1e9 + 7;
int n,k,ans;
int pw[N];
string s;
inline int qmi(int a,int b){
int res = 1;
while (b){
if (b & 1) res = Mul(res,a);
a = Mul(a,a);
b >>= 1;
}
return res;
}
inline void init(){
pw[0] = 1;
for (re int i = 1;i <= n;i++) pw[i] = Mul(pw[i - 1],2);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> s >> k;
n = s.size();
s = ' ' + s;
init();
for (re int i = 1;i <= n;i++){
if (s[i] == '0' || s[i] == '5') ans = Add(ans,Mul(pw[i - 1],Mul(Sub(qmi(pw[n],k),1),qmi(Sub(pw[n],1),mod - 2))));
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号