版权声明: https://blog.csdn.net/Ghost_Pig/article/details/82940401
- 这道题我们很明显的发现肯定是动态规划
- 当然以博主的智商,肯定是巧妙的推错了(留下苦涩的泪水)
- 正解的状态还听我慢慢道来
- 我们设f[i][j]为i个度数为2的点,其中j个点在环上(即剩下的i-j个点在链上)的方案数
- 得到了以下三种转移方程
- 然后发现链的个数是由度数为1的点的个数决定的
- 最后给出代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2005;
const ll mod = 998244353;
ll n,now,a1,a2,f[N][N],ans;
void In(ll &x)
{
ll f = 1;
x = 0;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
x = x * f;
return;
}
void Out(ll x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
{
Out(x / 10);
}
putchar(x % 10 + '0');
}
int main()
{
In(n);
for (ll i = 1; i <= n; i++)
{
In(now);
now&1?a1++:a2++;
}
if (a1&1)
{
putchar('0');
return 0;
}
f[0][0] = 1;
for (ll i = 1; i <= a2; i++)
{
for (ll j = 0; j <= i; j++)
{
if (j >= 3)
{
f[i][j] = f[i-3][j-3] * ((i - 1) * (i - 2) >> 1) % mod;
}
if (j >= 1)
{
f[i][j] = (f[i][j] + f[i-1][j-1] * (j-1)) % mod;
}
f[i][j] = (f[i][j] + f[i-1][j] * (a1 / 2 + i - j - 1)) % mod;
}
}
for (ll i = 0; i <= a2; i++)
ans = (ans + f[a2][i]) % mod;
for (ll i = 3; i <= a1; i++)
if (i & 1) ans = (ans *= i) % mod;
Out(ans);
return 0;
}