D. Fafa and Ancient Alphabet(概率dp)

, w a 19 开始想用模拟,但是wa19

d p 用概率dp可以很清晰的解决这个问题

f [ i ] [ 0 ] [ 1 , i ] a b 定义f[i][0]为[1,i]时a串等于b串的情况

f [ i ] [ 1 ] [ 1 , i ] a b f[i][1]为[1,i]时a串大于b串的情况

f [ n ] [ 1 ] 最后的答案就是\frac{f[n][1]}{总情况}

, \color{Red}由于转移情况太多,这里只举一个例子

a [ i ] = = 0 b [ i ] ! = 0 当a[i]==0且b[i]!=0时

f [ i ] [ 1 ] = f [ i 1 ] [ 1 ] m + f [ i 1 ] [ 0 ] ( m b [ i ] ) f[i][1]=f[i-1][1]*m+f[i-1][0]*(m-b[i])

? 啥意思?

, m 便 , f [ i 1 ] [ 1 ] m 前面赢了,这次m个数字随便选,就是f[i-1][1]*m

, ( m b [ i ] ) 使 b [ i ] , f [ i 1 ] [ 0 ] ( m b [ i ] ) 前面平局,则选(m-b[i])个数字使得比b[i]大,就是f[i-1][0]*(m-b[i])

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int maxn=1e5+10; 
int n,m,a[maxn],b[maxn],ans,f[maxn][2];
int quick_pow(int x,int n)
{
	int ans=1;
	while( n )
	{
		if( n&1 )	ans=ans*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return ans;
}
signed main()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)	cin >> a[i];
	for(int i=1;i<=n;i++)	cin >> b[i];
	f[0][0]=1;//相等的种数 
	int all=0;
	for(int i=1;i<=n;i++)
	{
		if( a[i]==0 )	all++;
		if( b[i]==0 )	all++;
		if( a[i]&&b[i] )
		{
			if( a[i]==b[i] )
				f[i][1]=f[i-1][1],f[i][0]=f[i-1][0];
			else if( a[i]>b[i] )
				f[i][1]=( f[i-1][0]+f[i-1][1] )%mod;
			else//a[i]<b[i]
				f[i][1]=f[i-1][1];//那么获胜的概率只能从前面继承 
		}
		else if( a[i]==0&&b[i]==0 )
		{
			f[i][1]=f[i-1][1]*m%mod*m%mod+f[i-1][0]*(m*(m-1)/2%mod)%mod;
			f[i][0]=f[i-1][0]*m%mod;
		}
		else if( a[i]==0 )
		{
			f[i][1]=f[i-1][1]*m%mod+f[i-1][0]*(m-b[i])%mod; //胜利 
			f[i][0]=f[i-1][0];
		}
		else if( b[i]==0 )
		{
			f[i][0]=f[i-1][0];
			f[i][1]=f[i-1][1]*m%mod+f[i-1][0]*(a[i]-1)%mod;
		}
		f[i][0]%=mod,f[i][1]%=mod;
	}
	cout << f[n][1]*quick_pow( quick_pow(m,all),mod-2 )%mod;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107846658