参观完各种饭堂,学校还有什么著名的景点呢?当然是教室了,此时此刻我
moreD 想知道对于一个n,可以有多少种不“重复”的矩阵,来填写不同
学生的信息,moreD 忙着更改身份认证系统,这个艰巨的任务就交给你了,你只
需要输出答案mod 100000007 的值就可以了,因为高一的学生可没有这么多。
输入格式:
第一行,一个整数t,表示数据组数。接下来t 行,每行一个整数n,表示一组数据。
输出格式:
T 行,每行一个整数,表示方案数。由于答案可能很大,只需要输出方案数mod 100,000,007 的值就可以了。
样例输入:
3 2 3 4
样例输出:
1 1 2
数据范围:
对于10%的数据 N≤5;对于50%的数据 N≤150;
对于100%的数据T≤5 N≤2,000。
时间限制:
1S空间限制:
256M比赛时暴力打表过了10分
那么先推结论
对于原来矩形上每一行每一列,分别看作一个点
那么对于矩形上的点,在对应的行和列的点连一条边
那么得到的图为一个二分图,点数为$2*n$,边数为$2*n$
因为矩形可以进行行列变化,那么答案就是这种二分图,在本质上不同的图的个数
而本质不同的二分图是不能通过交换列集或行集中的点,且不改变边的连接方式由其他二分图得到的
如上图,这两个二分图是本质相同的
那么可以发现如果两个二分图只要联通块的大小和个数不同那么它们就一定是本质不同的
而题目中保证每一行每一列必须有2个点
那么二分图中最小的联通块应该是2
那么最终的答案就是将n正整数拆分(正整数要大于等于2)的方案数
DP即可,枚举之前的数拆分方案累加即可
#include <bits/stdc++.h> #define mod 100000007 using namespace std; int t,n,dp[2100]; int main() { scanf("%d",&t); while (t--) { scanf("%d",&n); memset(dp,0,sizeof(dp)); dp[0]=1; for (int i=2;i<=n;i++) { for (int j=i;j<=n;j++) { dp[j]=(dp[j]+dp[j-i])%mod; } } printf("%d\n",dp[n]); } }