zoukankan      html  css  js  c++  java
  • HZOJ matrix

    完全没有思路,状压到死没调出来……吐槽一下这题目描述的好不清楚啊好多人都理解错题了……

    题解:

    真的挺神仙的,因为有每列最多放1个的限制,所以考虑按列dp,设f[i][j]表示考虑前i列在[1,i]中的右区间中有j个1,初始状态f[0][0]=1;注:以下右区间表示[r[u],m];

    记录l,r的前缀和sl,sr,但是这两个数组的含义并不一样,sl[i]表示前i列中有多少行左区间已经结束,sr[i]表示的则是前i列中有多少行右区间已经开始。

    转移:首先只考虑第i列,枚举右区间1的个数j,如果第i列不放1,那么$f[i][j]+=f[i-1][j]$,如果第i列放1,现在不考虑前i-1列的应响,$f[i][j]+=f[i-1][j-1]*(sr[i]-j+1)$,这里解释一下这个$sr[i]-j+1$,在前i列包括sr[i]行的右区间可以放1,而前i-1列已经放了$j-1$个1占据了$(j-1)$行,所以第i列能放1的行数为$(sr[i]-(j-1))$,由乘法计数原理得以上式子。但是我们这是没有考虑前i列左区间的情况:同样枚举右区间放k个1,此时有(sl[i]-sl[i-1])个左区间在第i列结尾,所以此时有(sl[i]-sl[i-1])个1必须要放,而有i-k-sl[i-1]个位置可以放1,所以要乘$A_{i-k-sl[i-1]}^{sl[i]-sl[i-1]}$,如果不合法会变成负数。最后f[m][n]即为最后答案。

     1 #include<iostream>
     2 #include<cstdio>
     3 #define LL long long
     4 #define int LL
     5 #define mod 998244353
     6 #define MAXN 3010
     7 using namespace std;
     8 int n,m,l[MAXN],r[MAXN];
     9 int sl[MAXN],sr[MAXN],f[MAXN][MAXN];
    10 signed main()
    11 {    
    12     cin>>n>>m;
    13     for(int i=1;i<=n;i++)cin>>l[i]>>r[i],sl[l[i]]++,sr[r[i]]++;
    14     for(int i=1;i<=m;i++)sl[i]+=sl[i-1],sr[i]+=sr[i-1];
    15     f[0][0]=1;
    16     for(int i=1;i<=m;i++)
    17     {
    18         f[i][0]=f[i-1][0];
    19         for(int j=1;j<=i;j++)    
    20             f[i][j]=(f[i-1][j]+f[i-1][j-1]*(sr[i]-j+1)%mod)%mod;
    21         for(int k=0;k<=i;k++)
    22         for(int j=sl[i-1];j<sl[i];j++)
    23             f[i][k]=f[i][k]*(i-k-j)%mod;            
    24     }
    25     printf("%lld
    ",f[m][n]);
    26 }
    View Code
  • 相关阅读:
    [Linux系统] (3)应用安装方式详解(编译安装、rpm包安装、yum安装)
    [Linux系统] (2)用户权限管理
    jQuery.Validate验证库详解
    jQuery Ajax 实例 ($.ajax、$.post、$.get)
    原生js记住密码
    静态网站公用的部分模块的引用(设置)方法
    针对特定浏览器起作用的CSS: IE Chrome Firefox CSS Hack
    HTML5 video 视频标签全属性详解
    js for循环,为什么一定要加var定义i变量
    用谷歌浏览器来当手机模拟器
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11286366.html
Copyright © 2011-2022 走看看