牛客练习110-D,E

题目链接:https://ac.nowcoder.com/acm/contest/54129/D

比赛的时候dp状态方程想错了,一直在做无用功。

思路:设\(dp[i]\)为用了i次魔法的期望值,递推地做即可。

hard版本:考虑字符串中的每一个字母对答案的贡献,每位数字没被选择的概率为\(p = {(n-1)^k/n}^k\),被选择的概率为\(p_1 = 1-p\),而变几次对答案是没有任何影响的,所以我们枚举字符串求每一位的贡献即可。

代码:

//easy版本
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
map<char,int>M;
long long qmod(long long x,long long y){
    long long res = 1;
    while(y){
        if (y&1) res = res*x%mod;
        y = y>>1;
        x = x*x%mod;
    }
    return res;
}
long long dp[2000];
int main(){
    int n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    M['y'] = 1;
    M['w'] = 1;
    M['i'] = 1;
    M['a'] = 1;
    M['k'] = 1;
    long long v1 = 5*qmod(26,mod-2)%mod;
    long long v2 = 21*qmod(26,mod-2)%mod;
    long long t = qmod(n,mod-2);
    for (int i=0;i<n;i++){
        if (M.count(s[i])) dp[0]++;
    }
    for (int i=1;i<=k;i++){
        dp[i] = dp[i-1];
        dp[i] = (dp[i]-dp[i-1]*t%mod*v2%mod+mod)%mod;
        dp[i] = (dp[i]+(n-dp[i-1]+mod)*t%mod*v1%mod)%mod;
    }
    cout<<dp[k]<<'\n';
}
//hard版本
#include<bits/stdc++.h>
using namespace std;
const long long mod = 1e9+7;
set<char>S;
long long qmod(long long x,long long y){
    long long res = 1;
    while(y){
        if (y&1) res = res*x%mod;
        y = y>>1;
        x = x*x%mod;
    }
    return res;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    long long n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    long long ans = 0;
    long long p = qmod((n-1)*qmod(n,mod-2)%mod,k);
    long long q = (1-p+mod)%mod;
    long long v = 5*qmod(26,mod-2)%mod;
    S.insert('y');
    S.insert('w');
    S.insert('k');
    S.insert('a');
    S.insert('i');
    for (int i=0;i<n;i++){
        if (S.count(s[i])){
            ans = (ans+p)%mod;
        }
        ans = (ans+q*v%mod)%mod;
    }
    cout<<ans;
}
posted @ 2023-04-15 10:56  安潇末痕  阅读(20)  评论(0)    收藏  举报