[题解]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;  
}  
posted @ 2024-06-23 12:59  WBIKPS  阅读(13)  评论(0)    收藏  举报