正题
题目链接:https://www.luogu.com.cn/problem/P5664
题目大意
对于nnn个方法,mmm个材料,一个方法配对一个材料可以做an,ma_{n,m}an,m道菜。选择kkk个配对要求
- 配对至少为k>1k>1k>1
- 每个配对的方法不同
- 每个材料最多用⌊k2⌋\lfloor\frac{k}{2}\rfloor⌊2k⌋次
求做菜方案数
解题思路
考虑容斥减去多余方案,也就是要求一个材料用超过一半。枚举这个超过一半的材料,设fi,jf_{i,j}fi,j表示选到第iii个方法,这个材料减去其他材料的使用次数为jjj,那么这个多余方案的答案就是jjj为正数的fff值。
时间复杂度O(n2m)O(n^2m)O(n2m)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=110,M=2100,XJQ=998244353;
ll n,m,a[N][M],f[N][2*N],s[N],ans=1;
int main()
{scanf("%lld%lld",&n,&m);for(ll i=1;i<=n;i++){for(ll j=1;j<=m;j++){scanf("%lld",&a[i][j]);(s[i]+=a[i][j])%=XJQ;}ans=ans*(s[i]+1)%XJQ;}for(ll k=1;k<=m;k++){memset(f,0,sizeof(f));f[0][n]=1;for(ll i=1;i<=n;i++)for(ll j=0;j<=2*n;j++){f[i][j]=f[i-1][j];if(j!=2*n)f[i][j]=(f[i][j]+f[i-1][j+1]*(s[i]-a[i][k]+XJQ)%XJQ)%XJQ;if(j!=0)f[i][j]=(f[i][j]+f[i-1][j-1]*a[i][k]%XJQ)%XJQ;}for(ll j=n+1;j<=2*n;j++)ans=(ans-f[n][j]+XJQ)%XJQ;}printf("%lld",(ans-1+XJQ)%XJQ);
}