HHDU5411 CRB and Puzzle

来源:互联网 发布:word 字数统计 mac 编辑:程序博客网 时间:2024/06/14 11:58

看了很久,问了好多,才懂个大概

假设A 为基本矩阵

基本的矩阵就是如果u能在v之后放,那矩阵元素a[u][v]=1,其它元素为0

把矩阵第i行第j列元素当做开头为i,结尾为j的方案数,那么当矩阵相乘时,这个元素就是i->u, u->j,所有的方案数加起来了,就是开头为i,结尾为j,且长度为3的方案数,类推,m次方就是长度为m的方案数。

A^i矩阵表示长度为i+1的方案情况
为什么A^i矩阵表示长度为i+1的方案情况呢?
拿样例
A=0 0 0
1 0 0
01 0

A^2的时候A[2][1]=2能放在1后面的方案=2在1后面*1在1后面 +2在2后面*2在1后面
对应的情况就是 排列如12的方案数*排列如11的方案数11 + 排列如22的方案数+排列如12的方案数
因为当长度为3的时候他们总是可以排列成 112 122 这样的序列

所以答案总方案数是
|E|+|A|+|A^2|+...+|A^(m-1)|+1,1指空集,|A|指A矩阵所有元素的和,E为单位矩阵
|E|+|A|+|A^2|+...+|A^(m-1)|+1=|E+A+A^2+...+A^(m-1)|+1


拿样例来说
3 2
1 2
1 3
0
那么基本矩阵A就是
0 0 0
1 0 0
01 0

A^i矩阵表示长度为i+1的方案情况
A^0,即单位矩阵
1 0 0
0 1 0
0 0 1
表示长度为1的情况,就是1,2,3
A^1
0 0 0
1 0 0
01 0

表示长度为2的情况:1-2 ,2-3
然后最大长度是m,所以A的最大质数就是m-1,加上空集,总共6种。

所以问题就是怎么求|E+A+A^2+...+A^(m-1)|元素和+1

http://blog.csdn.net/playwfun/article/details/47828723 这个方法好像用到了一个理论
就是E+A+A^2+...+A^(m-1)这个矩阵的元素和+1等于B矩阵的(m-1)次方的元素和
B矩阵指

[                0

   A,           0

                  .

                  .

1,1,1,1.....1]

最后一行全1,右边为0(除了最后一行)

不知道是什么道理,记住好了。。。


这里http://www.cnblogs.com/jiangjing/archive/2013/05/28/3103336.html介绍了一种求E+A+A^2+...+A^(m-1)

我用了这个模板改了,有个特别注意的地方就是

for (k = 1; k <= len; k++)c.p[i][j] +=a.p[i][k] * b.p[k][j];// c.p[i][j]=(a.p[i][k]*b.p[k][j]+c.p[i][j])%mod;原本是这一句,但是会T,改成下面就过了c.p[i][j] %= mod;                 //像上面那样写的话就是模 i*j*k 次,改成这样子就是模 i*j 次,好神奇!
AC代码

#pragma warning (disable:4996)#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio>#include <cstring>#include <iostream>using namespace std;struct node{int p[110][110];};int mod=2015, len;struct node suan(struct node a, struct node b)//矩阵a乘以矩阵b{int i, j, k;struct node c;for (i = 1; i <= len; i++){for (j = 1; j <= len; j++){c.p[i][j] = 0;for (k = 1; k <= len; k++)c.p[i][j] +=a.p[i][k] * b.p[k][j];// c.p[i][j]=(a.p[i][k]*b.p[k][j]+c.p[i][j])%mod;原本是这一句,但是会T,改成下面就过了c.p[i][j] %= mod;                 //像上面那样写的话就是模 i*j*k 次,改成这样子就是模 i*j 次,好神奇! }}return c;}struct node haha(struct node a, struct node b, int n){while (n)//矩阵的快速幂{if (n % 2 == 1)b = suan(b, a);n = n / 2;a = suan(a, a);}return b;}int main(){int i, j, n, m;int t;scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);struct node a, b;len = n * 2;int num; int x;memset(a.p, 0, sizeof(a.p));for (int i = 1; i <= n; i++){scanf("%d", &num);for (int j = 0; j < num; j++){scanf("%d", &x);a.p[x][i] = 1;}}for (i = 1; i <= n; i++)//右上部分for (j = n + 1; j <= n * 2; j++)if (i + n == j)a.p[i][j] = 1;elsea.p[i][j] = 0;for (i = n + 1; i <= n * 2; i++)//左下部分for (j = 1; j <= n; j++)a.p[i][j] = 0;for (i = n + 1; i <= 2 * n; i++)//右下部分for (j = n + 1; j <= n * 2; j++)if (i == j)a.p[i][j] = 1;elsea.p[i][j] = 0;for (i = 1; i <= n * 2; i++)//把b变成单位矩阵for (j = 1; j <= n * 2; j++)if (i == j)b.p[i][j] = 1;elseb.p[i][j] = 0;a = haha(a, b, m );int res = 0;for (i = 1; i <= n; i++){for (j = n + 1; j <=len; j++)res = (res + a.p[i][j] )% mod;}res =( res + 1) % mod;printf("%d\n",res );}return 0;}


0 0
原创粉丝点击