您的位置:首页 > 其它

hdu 5411 CRB and Puzzle 2015 多校联合训练赛#10 快速矩阵幂

2015-08-20 20:18 435 查看


CRB and Puzzle

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 69 Accepted Submission(s): 35



Problem Description

CRB is now playing Jigsaw Puzzle.

There are N kinds
of pieces with infinite supply.

He can assemble one piece to the right side of the previously assembled one.

For each kind of pieces, only restricted kinds can be assembled with.

How many different patterns he can assemble with at most M pieces?
(Two patterns P and Q are
considered different if their lengths are different or there exists an integer j such
that j-th
piece of P is
different from corresponding piece of Q.)



Input

There are multiple test cases. The first line of input contains an integer T,
indicating the number of test cases. For each test case:

The first line contains two integers N, M denoting
the number of kinds of pieces and the maximum number of moves.

Then N lines
follow. i-th
line is described as following format.

k a1 a2 ... ak

Here k is
the number of kinds which can be assembled to the right of the i-th
kind. Next k integers
represent each of them.

1 ≤ T ≤
20

1 ≤ N ≤
50

1 ≤ M ≤ 105

0 ≤ k ≤ N

1 ≤ a1 < a2 <
… < ak ≤
N



Output

For each test case, output a single integer - number of different patterns modulo 2015.



Sample Input

1
3 2
1 2
1 3
0




Sample Output

6
Hintpossible patterns are ∅, 1, 2, 3, 1→2, 2→3




Author

KUT(DPRK)



Source

2015 Multi-University Training Contest 10

建立转移矩阵,增加一个结点,表示ans的情况即可。

===========================

根据有人评论,如何记录ans的数量的。我们现在假设以下方程A是转移矩阵,有三种状态

如果是线性的转移,那么每一次转移,ans += dp[1]+dp[2]+dp[3],这样就记录了当前长度的答案了。

如何在矩阵中实现到ans的转移呢?

在矩阵中加入ans这个状态,由于刚开始,长度为0的种类有一个,构造如下矩阵与状态A表示转移矩阵。

A[1,1,1,1] = A[dp[1],dp[2],dp[4],ans] ( 长度为1的情况下,任何数都可以放,所以都是1)

接下来是如何构造A使得每次乘上A,都会使得ans更新:

如下 A =

x x x 0 dp[1]

x x x 0 * dp[2]

x x x 0 dp[3]

1 1 1 1 ans

那么可知每次乘A,dp值都会变,dp值表示长度为当前长度,以i结尾的情况数。

那么在这次乘法中 ans = dp[1] + dp[2] + dp[3] + ans , ans不仅记录了上一次的值,并且还加上了上一次的

dp[1],dp[2],dp[3]的值,也就是说,ans是不同长度的情况下的累加和。

那么用矩阵加速也就能理解。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int mod = 2015;
const int maxn = 52;

struct Node{
    int mat[maxn][maxn];
    Node(){
        memset(mat,0,sizeof(mat));
    }
};

Node operator*(Node a,Node b){
    Node c;
    for(int i = 0;i < maxn; i++)
        for(int j = 0;j < maxn; j++)
            for(int k = 0;k < maxn; k++)
                c.mat[i][j] += a.mat[i][k]*b.mat[k][j];
    for(int i = 0;i < maxn; i++)
        for(int j = 0;j < maxn; j++)
            c.mat[i][j] %= mod;
    return c;
}

int main(){
    int t,n,m;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        Node a,b,c;
        for(int i = 0;i < n; i++){
            int k;
            scanf("%d",&k);
            while(k--){
                int u;
                scanf("%d",&u);
                u--;
                a.mat[u][i] = 1;
            }
        }
        for(int i = 0;i <= n; i++)
            a.mat
[i] = 1;
        for(int i = 0;i <= n; i++)
            b.mat[i][i] = 1;
        int ans = 0;

        while(m){
            if(m&1) b = a*b;
            a = a*a;
            m/=2;
        }

        for(int i = 0;i <= n; i++)
            ans += b.mat
[i];
        ans %= mod;
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: