CodeForces 489F DP Special Matrices

首先统计一下前m行中,有x列1的个数为0,有y列1的个数为1.

设d(i, j)表示有i列1的个数为0,有j列1的个数为1,能到达这个状态的矩阵的个数。

则d(x, y) = 1

每一行都是两个1一起放,枚举这两个1分别放在了哪种列上面

于是有状态转移:

  • d(i - 2, j + 2) += d(i, j) * C(i, 2)
  • d(i - 1, j) += d(i, j) * i * j
  • d(i, j - 2) += d(i, j) * C(j, 2)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 const int maxn = 500 + 10;
 8
 9 int n, m;
10
11 long long d[maxn][maxn], MOD;
12
13 char s[maxn];
14 int cnt[maxn];
15
16 int main()
17 {
18     scanf("%d%d%I64d", &n, &m, &MOD);
19     for(int i = 0; i < m; i++)
20     {
21         scanf("%s", s);
22         for(int j = 0; j < n; j++) if(s[j] == ‘1‘) cnt[j]++;
23     }
24
25     int zero = 0, ones = 0;
26     for(int i = 0; i < n; i++) if(!cnt[i]) zero++; else if(cnt[i] == 1) ones++;
27
28     d[zero][ones] = 1;
29     for(int i = n; i >= 0; i--)
30         for(int j = n; j >= 0; j--)
31         {
32             if(i >= 2) d[i-2][j+2] = (d[i-2][j+2] + d[i][j] * i * (i - 1) / 2) % MOD;
33             if(i && j) d[i-1][j] = (d[i-1][j] + d[i][j] * i * j) % MOD;
34             if(j >= 2) d[i][j-2] = (d[i][j-2] + d[i][j] * j * (j - 1) / 2) % MOD;
35         }
36
37     printf("%I64d\n", d[0][0]);
38
39     return 0;
40 }

代码君

时间: 2024-08-30 05:17:08

CodeForces 489F DP Special Matrices的相关文章

codeforces 449D DP+容斥

Jzzhu and Numbers Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-20) Description Jzzhu have n non-negative integers a1, a2, ..., an. We will call a sequence o

codeforces 489F Special Matrices(DP)

传送门:点击打开链接 题目大意: 给定一个n*n的01矩阵的前m行,要求求出有多少种构造方案使得:每一行,每一列的1的个数都是2 解题思路: 既然已经给定了前m行,那么就相当于告诉了我们有哪几列,还能放2个1,1个1,和不能再放1了. 注意到,这个时候列之间是可以交换的,那么就可以做了. 定义dp[i][j][k]表示在第i行剩j个位置可以放2个1,剩k个位置可以放1个1. 因为下一行一定要放2个1,那么就有3种转移状态: 1:全部选的是放2个的.那么就转移到了dp[i+1][j-2][k+2]

CodeForces 489F Special Matrices

题意: n(500)*n的矩阵  每行每列只有两个1  现在给出前m行  问  有几种合法的矩阵 思路: 只需要考虑每列上有几个1  然后按行扫描  每次维护行内只有2个1  这样就能构造出合法矩阵 那么我们定义dp[i][j][k]表示扫描到第i行有j列是包含1个1的有k列是包含2个1的  这时500^3数组开不下  于是滚动i 那么对于dp[i][j][k] 如果n-j-k>=2  则可以选择两列分别填1  即转移到dp[i+1][j+2][k] 如果n-j-k>=1&&j

CodeForces 706C dp

C - Hard problem Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 706C Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so he as

codeforces的dp专题

1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个序列求和的最大值是多少 分析:设dp[i][j]在[j,n]范围内取了i个子序列求和所得的最大值,用sum[i]表示[1,i]的求和.转移方程为dp[i][j]=max(dp[i-1][j+m]+sum[j+m-1]-sum[j-1],dp[i][j+1]),表示要不要选择[j,j+m-1]这段为其

codeforces 711C dp

一眼dp,但是这道题不知怎么搞遇到点小问题,又搞了搞才出来,就是给你一些颜色.这个点有颜色,不能图,反之可以.问形成k段连续颜色的最小花费. 纯纯的dp,不知道为什么就是有问题...终于借鉴了别人的A过了,后面再研究吧. #include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <stack> #include <cstdlib>

Codeforces 404D [DP]

/* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01四种字符组成的字符串,类似扫雷,?代表当前不确定,0代表当前无雷,并且 两边无雷,1代表当前五雷且两边有一个雷,2同样的,问当所有格子已知以后一共有多少种可能的局面. 思路: 首先想到的是,这个问题无后效性,而当前位置的合法方式只与它之前的两位有关. 所以dp的思路也是显而易见的,即dp[i][j]

codeforces 608C:(dp)

从又往左点灯塔,点亮一个的同时,往左di范围内的灯塔全部被破坏.现在能在最右端按一个灯塔,攻击范围任意,问到最后最少有几个灯塔留下 用dp瞎搞.具体看代码吧 #include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include&quo

Codeforces 721C [dp][拓扑排序]

/* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG),这题一定可以dp. 2.dp[i][j]代表,到达点i,并且拜访了j个城市的最短时间. wa点: 没有初始化数组中的0.. */ #include<bits/stdc++.h> #define N 5050 using namespace std; int inf=0x3f3f3f3f; int