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; }
相关文章推荐
- floyd离散,最小环
- WebAPI身份验证
- HDU-2642-Stars
- Android-用你自己的自定义图像资源(2)
- 开源许可协议总结
- 结构体
- Bridging signals
- hdoj 1242 Rescue
- 用C语言编程求青蛙王子问题
- POJ1477
- HDU 4348 I - To the moon 可持续化
- HDOJ 2041 超级楼梯 (打表法)
- this指针与__thiscall调用方式
- Mysql多实例之mysql服务脚本
- Linux定时任务crontab
- CODEVS 3286 火柴排队
- Oracle Coherence中文教程二十一:使用缓存事件
- HDOJ 2199 Can you solve this equation? (二分法)
- Rotate Array [LeetCode]
- 算法导论——(4)有序统计树(OrderStatisticTree,以红黑树为基本数据结构)