hdu 5411 CRB and Puzzle【矩阵快速幂】

CRB and Puzzle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1013    Accepted Submission(s): 402

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

Hint

possible patterns are ∅, 1, 2, 3, 1→2, 2→3


Author

KUTDPRK


Source

2015 Multi-University Training Contest 10

 

 题目大意:第一行输入一个t,表示测试数据的组数,第二行输入n,m,表示一共有n个节点,让你求出在走m步的条件限制下,一共能够有多少种走的方式。

 

思路:

首先我们看这样一个矩阵,作为一个原矩阵。

其中a【1】【2】=1;a【2】【3】=1,表示1能够到达2,2能够到达3、



然后我们将这个矩阵右乘一个自己(也就是说平方),得出这样一个矩阵:


不难理解,根据Floyd思想递推之后,a【1】【3】=1的含义为:从1到3距离为2的边数为1条。

那么我们有这样一个结论:我们求:a(距离)【1】【3】;就是在求原矩阵的距离次方上,a【1】【3】的数值。


学过离散的小伙伴们,对这个东西应该还是蛮熟悉的。


那么我们要求小于m步数的路的个数和,其实就是在求矩阵A,A^2,A^3,A^4.....a^m-1次方的所有元素和。

因为直接暴力m-1次求解会超时,所以我们再在矩阵下边再填上一层1,就能够达到求和的目的:



也就是说我们初始化矩阵为上图那样之后 ,再求一次A^(m-1)的矩阵快速幂之后,再将所有矩阵元素加和,就是我们要求的结果。


AC代码:


#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 2015
typedef struct Matrix
{
    int mat[55][55];
}matrix;
matrix A,B;
int n,m;
Matrix matrix_mul(matrix a,matrix b)
{
    matrix c;
    memset(c.mat,0,sizeof(c.mat));
    int i,j,k;
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            for(int k=0;k<=n;k++)
            {
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
                c.mat[i][j]%=mod;
            }
        }
    }
    return c;
}
Matrix matrix_quick_power(matrix a,int k)//矩阵快速幂0.0
{
    matrix b;
    memset(b.mat,0,sizeof(b.mat));
    for(int i=0;i<=n;i++)
    b.mat[i][i]=1;//单位矩阵b
    while(k)
    {
        if(k%2==1)
        {
            b=matrix_mul(a,b);
            k-=1;
        }
        else
        {
            a=matrix_mul(a,a);
            k/=2;
        }
    }
    return b;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(A.mat,0,sizeof(A.mat));
        for(int i=0;i<n;i++)
        {
            int k;
            scanf("%d",&k);
            while(k--)
            {
                int x;
                scanf("%d",&x);
                x--;
                A.mat[i][x]=1;
            }
        }
        for(int i=0;i<=n;i++)
        {
            A.mat[n][i]=1;
        }
        B=matrix_quick_power(A,m-1);
        int output=0;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            {
                output=(output+B.mat[i][j])%mod;
            }
        }
        printf("%d\n",output%mod);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值