Generating Texts
题目描述:
题目讲述的是,Lucko要去投注一个彩票,这个彩票是要Lucko去猜一个长度为n的字符串,如果Lucko能够猜出这个字符串其中一个子串的话,那么Lucko就能够获胜,现在输入一个长度为m的字符串,代表的是Lucko所给出的答案,并且给出这个长度为n的字符串中每个小写字母在字符串当中出现的概率,现在让我们求Lucko猜中的概率,答案需要对1e9+7取模。
题目分析:
这个题目首先先将每个小写字母在字符串当中出现的概率对1e9+7取模,由于涉及除法运算,因此需要求逆元,接下来我们可以用DP去求出Lucko获胜的概率。
首先我们定义一个二维数组dp[i][j],i表示的是长度为n的字符串的第几个字符,j表示的是长度为m的字符串的第几个字符,dp[i][j]表示的是长度为m的字符串的长度为j的前缀是长度为n的字符串的长度为i的前缀的子串的概率。
根据这个定义,我们可以得出状态转移方程:
其中p数组记录的是每个小写字母在字符串当中的出现概率,s表示输入的长度为m的字符串。
最终答案为
值得注意的是,上面的运算均要对1e9+7取模。
代码:
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <cstring>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <deque>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define eps 1e-3
#define mod 1000000007
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=5005;
const int Maxm=5005;
char s[Maxm];
ll p[30],dp[Maxn][Maxm];
ll Flt(ll n,int t)
{
ll ans=1;
while (t)
{
if (t&1) ans=ans*n%mod;
n=n*n%mod;
t>>=1;
}
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for (int i=1;i<=26;i++)
{
int q;
cin>>p[i]>>q;
p[i]=p[i]*Flt(q,mod-2)%mod;
}
dp[0][0]=1;
for (int i=1;i<=n;i++)
{
for (int j=0;j<=min(m-1,i);j++)
{
dp[i][j]+=dp[i-1][j]*((1-p[s[j+1]-96]+mod)%mod)%mod;
dp[i][j+1]+=dp[i-1][j]*p[s[j+1]-96]%mod;
}
}
ll ans=0;
for (int i=m;i<=n;i++) ans=(ans+dp[i][m])%mod;
cout<<ans<<endl;
return 0;
}