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

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.
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
KUT(DPRK)
 

Source

建立转移矩阵,增加一个结点,表示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[n][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[n][i];
        ans %= mod;
        printf("%d\n",ans);
    }
    return 0;
}














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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值