随笔 - 531  文章 - 0  评论 - 3  阅读 - 10215 

给出一个矩阵,要求每行只能选一个节点,每列选的节点不能超过所有选的节点的一半,给出每个节点的选择方案数(a[i][j] )

不能完全不选,求总方案数

 

直接容斥,ALL - 存在一个列的所选个数超过一半

但是发现这种列只能存在一个(脑补

 

枚举这个列,  对这个列做dp : F [ i] [j ][ k ], 前i行  ,该列所选个数为j ,未选的个数为k, 的方案数

F[ i ] [ j ] [k] = F[i-1][j][k]

F[i][j][k] += F[ i - 1][ j-1 ] [ k ]  *a[i][column]

    +=F[i-1][ j ][k-1] * (s[i] -a[i][column] )

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std ;
  const int N =102,M =2100;
  const int mod = 998244353 ;
   
  #define int long long
  int A[M],B[M];
  int f[N][N][N],n,m,a[N][M],s[N];
   
 void solve(){
    int i,j;
    int ALL=1;
    cin>>n>>m;
    for(i=1;i<=n;i++){
        s[i]=0;
        for(j=1;j<=m;j++)
            cin>>a[i][j],s[i]+=a[i][j],s[i]%=mod;
        ALL*= (s[i]+1),ALL%=mod;
    }
     
    int answer =0;
    for(int p=1;p<=m;p++){
        memset(f,0,sizeof f);
        for(i=1;i<=n;i++)
            A[i]=a[i][p],B[i]=(s[i]-A[i]+mod)%mod;
         
        f[0][0][0]=1;
        for(i=1;i<=n;i++)
         for(j=0;j<=i;j++)
          for(int k=0;k<=i-j;k++){
            f[i][j][k]=f[i-1][j][k];
             
            if(j>=1) f[i][j][k]+=(f[i-1][j-1][k]*A[i]);
            if(k>=1) f[i][j][k]+=(f[i-1][j][k-1]*B[i]);
            f[i][j][k]%=mod;
          }
        for(i=1;i<=n;i++)
        for(j=0;j<=n-i;j++)
         if(i>j) answer+=f[n][i][j],answer%=mod;
    }
     
      cout<< (ALL-answer-1+mod)%mod <<endl;
 }
 signed main(){
    solve();
 }

 

posted on   towboat  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示