首页 > 代码库 > CodeForces 489F Special Matrices
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>=1 则可以把某个1的列变成2 同时把0的列变成1 即转移到dp[i+1][j][k+1]
如果j>=2 则可以选择两个1变成2 即转移到dp[i+1][j-2][k+2]
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> #include<bitset> using namespace std; typedef long long LL; #define N 510 int n, m, mod; int dp[2][N][N]; int num[N]; char s[N]; void add(int &x, int y) { x += y; if (x >= mod) x -= mod; } int main() { scanf("%d%d%d", &n, &m, &mod); for (int i = 1; i <= m; i++) { scanf("%s", s + 1); for (int j = 1; j <= n; j++) { if (s[j] == '1') num[j]++; } } int j = 0, k = 0; for (int i = 1; i <= n; i++) { if (num[i] == 1) j++; else if (num[i] == 2) k++; } dp[m & 1][j][k] = 1; for (int i = m + 1; i <= n; i++) { memset(dp[i & 1], 0, sizeof(dp[i & 1])); for (j = 0; j <= n; j++) { for (k = 0; k + j <= n; k++) { if (dp[(i & 1) ^ 1][j][k]) { int zero = n - j - k, one = j, two = k; LL key = dp[(i & 1) ^ 1][j][k]; if (zero >= 2) add(dp[i & 1][one + 2][two], (LL) (zero) * (zero - 1) / 2 % mod * key % mod); if (zero >= 1 && one >= 1) add(dp[i & 1][one][two + 1], key * zero % mod * one % mod); if (one >= 2) add(dp[i & 1][one - 2][two + 2], (LL) (one) * (one - 1) / 2 % mod * key % mod); } } } } printf("%d\n", dp[n & 1][0][n]); return 0; }
CodeForces 489F Special Matrices
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。