P4921 [MtOI2018] 情侣?给我烧了! 题解(评分:7.3)
前言
普通的计数题,我们普通地 dp。
这是一个不带脑子的 dp 做法。
Solution
观察数据范围:
本题只有一个
T=1000 的数据点。。。暴力还是算了吧!
这不就是让我们把
这启示我们直接 dp!
设
现在考虑加上一对新的推出
先钦定两个人,男的先选(不考虑南通)
-
这对新的有可能坐一起,此时有
2\times (i+1) 种情况(男的随便选,妹子只能坐他旁边)此时其他的必然不打乱,所以总共坐一起的小情侣增加一对。
对应:
dp_{i+1,j+1}→dp_{i+1,j+1}+2\times (i+1)\times dp_{i,j} -
这对新的没有坐一起,共有
(2\times i+2)\times 2\times i 种情况(妹子除了不坐他旁边还有2\times i 个位置可以选择)。这样还可能打乱前面的,我们钦定这种情况时候,前面2\times (i-1) 个人的位置不变,最后两人依次和这新来的两个人坐。显然坐一起的小情侣不会增加,而且会减少一对,当且仅当本来坐最后一排两个位置的是小情侣。
但是在本来的
dp_{i,j} 种情况中,容易发现只有\frac{j}{i} 的情况下坐最后一排两人是一对。那我们分开转移即可,具体的:
dp_{i+1,j-1}→dp_{i+1,j-1}+dp_{i,j}\times (2\times i+2)\times 2\times i\times \frac{j}{i} dp_{i+1,j}→dp_{i+1,j}+dp_{i,j}\times (2\times i+2)\times 2\times i\times \frac{i-j}{i}
式子里有除法,但是可以约掉而不用写逆元。
搞定。
这里祝天下 xql 一律 99。()
AC Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mod 998244353
int dp[1005][1005],i,j;
signed main()
{
dp[1][1]=2;
for(i=1;i<=999;i++)
for(j=0;j<=i;j++) if(dp[i][j])
{
dp[i+1][j+1]=(dp[i+1][j+1]+2ll*(i+1)*dp[i][j])%mod;
int dw=dp[i][j]*(i*4+4)%mod,br=dw*j,nb=dw*(i-j);
if(j) dp[i+1][j-1]=(dp[i+1][j-1]+br)%mod;
(dp[i+1][j]+=nb)%=mod;
}
int T;cin>>T;
while(T--)
{
int n;
cin>>n;
for(i=0;i<=n;i++) cout<<dp[n][i]<<endl;
}
return 0;
}