[PA2021] Od deski do deski 题解

好题好题,难者不会会者不难,我是前者。


实际上加入就可以合法的数是很好计算的。考虑现在所有前缀合法串后的字符实际上都可以满足条件。

容易想到根据是否合法设置状态。设 \(f_{i,j}/g_{i,j}\) 表示现在填第 \(i\) 个数,有 \(j\) 个填了就合法的数,现在的串合法/不合法。

那么有转移方程:

  1. \(f_{i+1,j}=j\times(f_{i,j}+g_{i,j})\),这个很好理解,就是添加了一个加了就合法的数。

  2. \(g_{i+1,j+1}+=(m-j)\times f_{i,j}\),添加了一个加了不能合法的数,但是再加一次就能合法。

  3. \(g_{i+1,j}+=(m-j)\times g_{i,j}\),添加了一个加了不能合法的数,但是由于本身就不合法,所以没啥用。

时间复杂度 \(O(n^2)\),可以通过本题。

#include<bits/stdc++.h>
using namespace std;
const int N=3005,p=1e9+7;
int n,m,f[N][N],g[N][N],ans;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m,g[1][1]=m;
	for(int i=1;i<n;i++)
		for(int j=1;j<=i;j++){
			f[i+1][j]=1ll*j*(f[i][j]+g[i][j])%p;
			g[i+1][j+1]=1ll*(m-j)*f[i][j];
			g[i+1][j]=(g[i+1][j]+1ll*(m-j)*g[i][j]%p)%p;
		}
	for(int i=1;i<=n;i++)
		ans=(ans+f[n][i])%p;
	cout<<ans;
	return 0;
} 
posted @ 2024-10-14 19:14  长安一片月_22  阅读(8)  评论(0编辑  收藏  举报