hihocoder 1124 : 好矩阵 dp

好矩阵

时间限制:3000ms

单点时限:1000ms

内存限制:256MB

描述

给定n, m。一个n?×?m矩阵是好矩阵当且仅当它的每个位置都是非负整数,且每行每列的和?≤?2。求好矩阵的个数,模109?+?7

输入

第一行一个整数T,表示测试点个数。下面T个测试点。每个测试点一行,包含两个整数n,m。1?≤?T?≤?104. 1?≤?n,?m?≤?100.

输出

T行。每行是对应测试点的答案。

样例输入
1
2 2
样例输出
26

题意很简单,由于,数量很大,如果考虑一个一个方格的放,要考虑横向的,又要考虑竖向的,很复杂,所以不可取。所以一排一排的放,如果,m是一定的,那么,每一排只需要考虑不超过2,且与前面已经排好的不冲突就可以了。

dp[i][a][b]表示,第i排,有a列0,b列1,m - a - b列2,的个数则

dp[i+1][a][b]+= dp[i][a][b];//第i+1排全放0

dp[i+1][a-1][b] += (ll)a * dp[i][a][b];//第i+1排在和为0那些列放一个2

dp[i+1][a-1][b+1] += (ll)a * dp[i][a][b];//第i+1排和为1放一个1

dp[i+1][a-1][b]+= (ll)a * (ll) b * dp[i][a][b];//第i+1排和为0 和为1的列各选一个 放两个1

dp[i+1][a][b-1] += (ll)b * dp[i][a][b];//第i+1排选一个和为1的列放一个1

dp[i+1][a-2][b+2] += (ll)(a * (a-1)/2) * dp[i][a][b];//第i+1排选两个和为0放两个1

dp[i+1][a][b-2] += (ll)(b * (b-1)/2) * dp[i][a][b];//第i+1排选两个和为1的放两个1

总复杂度为o(n^4);

#define N 105
#define M 100005
#define maxn 205
#define MOD 1000000007
int n,m,T;
ll dp[N][N][N],ans[N][N];
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    for(int m = 1;m<=100;m++){
        int n = 100;
        for(int i =0;i<=n;i++){
            for(int a = 0;a<=m;a++){
                for(int b = 0;b<=m;b++){
                    dp[i][a][b] = 0;
                }
            }
        }
        dp[0][m][0] = 1;
        for(int i = 0;i<n;i++){
            for(int a = 0;a<=m;a++){
                for(int b = 0;a + b<=m;b++){
                    dp[i+1][a][b]+= dp[i][a][b];
                    dp[i+1][a][b] %= MOD;
                    if(a >= 1){
                        dp[i+1][a-1][b] += (ll)a * dp[i][a][b];
                        dp[i+1][a-1][b] %= MOD;
                        dp[i+1][a-1][b+1] += (ll)a * dp[i][a][b];
                        dp[i+1][a-1][b+1] %= MOD;
                    }
                    if(a >= 1 && b >= 1){
                        dp[i+1][a-1][b]+= (ll)a * (ll) b * dp[i][a][b];
                        dp[i+1][a-1][b] %= MOD;
                    }
                    if(b >= 1 ){
                        dp[i+1][a][b-1] += (ll)b * dp[i][a][b];
                        dp[i+1][a][b-1] %= MOD;
                    }
                    if(a >= 2 ){
                        dp[i+1][a-2][b+2] += (ll)(a * (a-1)/2) * dp[i][a][b];
                        dp[i+1][a-2][b+2] %= MOD;
                    }
                    if(b >= 2 ){
                        dp[i+1][a][b-2] += (ll)(b * (b-1)/2) * dp[i][a][b];
                        dp[i+1][a][b-2] %= MOD;
                    }
                }
            }
            ans[i+1][m] = 0;
            for(int a = 0;a<=m;a++){
                for(int b = 0;b<=m;b++){
                    ans[i+1][m] += dp[i+1][a][b];
                    ans[i+1][m] %= MOD;
                }
            }
        }
    }
    while(S(T)!=EOF)
    {
        while(T--){
            int s,e;
            S2(s,e);
            printf("%lld\n",ans[s][e]);
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-19 16:49:17

hihocoder 1124 : 好矩阵 dp的相关文章

hdu 4975 最大流问题解决队伍和矩阵,利用矩阵dp优化

//刚開始乱搞. //网络流求解,假设最大流=全部元素的和则有解:利用残留网络推断是否唯一, //方法有两种,第一种是深搜看看是否存在正边权的环.见上一篇4888 //至少四个点构成的环,另外一种是用矩阵dp,仅仅须要满足某行的i列元素<9,j列元素>0,而还有一行的i列元素>0,j列元素<9, //能够满足互补就证明不唯一.这个绘图不难看出 #include<stdio.h> #include<string.h> #include<queue>

[hihocoder 1033]交错和 数位dp/记忆化搜索

#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0,?a1,?...,?an?-?1,定义交错和函数: f(x)?=?a0?-?a1?+?a2?-?...?+?(?-?1)n?-?1an?-?1 例如: f(3214567)?=?3?-?2?+?1?-?4?+?5?-?6?+?7?=?4 给定 输入 输入数据仅一行包含三个整数,l,?r,?k(0?≤?l?≤?r?≤?1018,?|k|

hdu 4975 最大流解决行列和求矩阵问题,用到矩阵dp优化

//刚开始乱搞. //网络流求解,如果最大流=所有元素的和则有解:利用残留网络判断是否唯一, //方法有两种,第一种是深搜看看是否存在正边权的环,见上一篇4888 //至少3个点构成的环,第二种是用矩阵dp,只需要满足某行的i列元素<9,j列元素>0,而另一行的i列元素>0,j列元素<9, //可以满足互补就证明不唯一,这个画图不难看出 #include<stdio.h> #include<string.h> #include<queue> us

hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 579    Accepted Submission(s): 194 Problem Description Drag

bnu oj 34985 Elegant String (矩阵+dp)

Elegant String We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,-, k". Let function(n, k) be the number of elegant strings of length n which only contains digits

POJ2778&amp;HDU2243&amp;POJ1625(AC自动机+矩阵/DP)

POJ2778 题意:只有四种字符的字符串(A, C, T and G),有M中字符串不能出现,为长度为n的字符串可以有多少种. 题解:在字符串上有L中状态,所以就有L*A(字符个数)中状态转移.这里自动机的build的hdu2222略有不同. 那一题中通过询问时循环来求she的he,但是如果he不能出现,she就算不是禁止的字符串也不可出现,所以在build的时候就记录所有不能出现的状态. if (end[ fail[now] ]) end[now]++; 然后用一个矩阵F来记录可以相互到达的

#1124 : 好矩阵

描述 给定n, m.一个n × m矩阵是好矩阵当且仅当它的每个位置都是非负整数,且每行每列的和 ≤ 2.求好矩阵的个数,模109 + 7 输入 第一行一个整数T,表示测试点个数.下面T个测试点.每个测试点一行,包含两个整数n,m.1 ≤ T ≤ 104. 1 ≤ n, m ≤ 100. 输出 T行.每行是对应测试点的答案. 样例输入 1 2 2 样例输出 26 应该算是比较常规的DP题,有点卡时. #include<cstdio> #include<cctype> #include

hihoCoder #1033 : 交错和 [ 数位dp ]

传送门 #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1 例如: f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = k 的 x 的和,即

HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解

题意:01串,操作1:把l r区间的0变1,1变0:操作2:求出l r区间的子序列种数 思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] + dp[i -1][0] (0结尾新串) + dp[i - 1][0] (0结尾旧串) - dp[i - 1][0] (重复) + 1(0本身被重复时去除). 那么可以得到转移时的矩阵 $$ \left( \begin{matrix} dp[i - 1][0] & dp[i - 1][1] &am