【HDU5411 2015 Multi-University Training Contest 10F】【矩阵快速幂 加一行构造法】CRB and Puzzle 矩阵的1次方到n次方的数值和

原创 2015年11月20日 12:08:05


CRB and Puzzle

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


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

Source
 



#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=51,M=0,L=0,Z=2015,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
const double eps=1e-8,PI=acos(-1.0);//.0
map<int,int>mop;
struct A{};
int casenum,casei;
int n,m,nn;
struct MX
{
	int v[N][N];
	void O(){MS(v,0);}//得到零矩阵
	void E(){MS(v,0);for(int i=0;i<nn;i++)v[i][i]=1;}//得到单位矩阵
	MX operator * (const MX &b) //const 这个const 有什么用处呢——确保我们不改变b的值
	{
		MX c;c.O();
		for(int k=0;k<nn;k++)
		{
			for(int i=0;i<nn;i++)
			{
				for(int j=0;j<nn;j++)
				{
					c.v[i][j]=(c.v[i][j]+v[i][k]*b.v[k][j]);
				}
			}
		}
		for(int i=0;i<nn;i++)
		{
			for(int j=0;j<nn;j++)c.v[i][j]%=Z;
		}
		/*
		计算的大量时间浪费在取模上了。
		v[i,j]最多只能累计2015*2015*100的权值,也就是4e8,不会爆int
		这样优化就AC了。
		*/
		return c;
	}
	MX operator ^ (int p)
	{
		MX x;x.E();//初始化单位矩阵
		MX y;MC(y.v,v);
		while(p)
		{
			if(p&1)x=x*y;
			p/=2;
			y=y*y;
		}
		return x;
	}
}a;
int main()
{
	//fre();
	scanf("%d",&casenum);
	for(casei=1;casei<=casenum;casei++)
	{
		a.O();
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++)
		{
			int k,x;scanf("%d",&k);
			for(int j=0;j<k;j++)
			{
				scanf("%d",&x);
				a.v[i][x-1]=1;
			}
		}
		for(int i=0;i<=n;i++)a.v[i][n]=1;
		nn=n+1;a=a^(m-1);//运算^m得到的是E+A+A^2+...+A^(m-1)
		int ans=0;
		for(int i=0;i<nn;i++)
		{
			for(int j=0;j<nn;j++)ans+=a.v[i][j];
		}
		printf("%d\n",ans%Z);
	}
	return 0;
}
/*
【题意】
有n(1<=n<=50)种纸片,每种无限个。
我们每次可以仿制一张卡片,放到被仿制卡片的右边。
我们想知道,使用0~m(1<=m<=1e5)张纸后可以创造出多少种图案。

【类型】
矩阵快速幂

【分析】
一开始首先我们得到的是一个矩阵。
aij表示图案i可以在右侧仿制出图案j
然后就矩阵快速幂搞一下就可以啦~

【时间复杂度&&优化】
然而这道题,我用的是一个技巧。
求A^0+A^1+A^2+...+A^m,可以构造这样的矩阵——
AE
OE
然后上面那个矩阵做^(m+1),然后得到矩阵——
AB
CD
B就等于A^0+A^1+A^2+...+A^m

只是这种方法使得常数扩大了8倍,也许会导致TLE
于是我们还要用迭代法试试看,然后也TLE
然而如果做了取模优化了,还是能够就AC,只是并不快>_<

===========★再看看题解构造法★============
时间效率快了至少5倍啊!太厉害了!
是怎么实现的呢?
设原矩阵为
AB
CD
那么新矩阵就成了
AB0
CD0
111
如果m=1,我们返回a^0,即单位矩阵,只存在对角线元素n+1个
如果m=2,我们返回a^1,即如下原矩阵,结果也对
AB0 AB0
CD0 CD0
111 111
如果m=3,对于我们返回的矩阵
左上角的n*n矩阵依然会得到原矩阵平方的结果,也就相当于求得了A^2
然后下面这个111……就把之前的全部结果都存进来了
而且形成的矩阵永远是
AB0
CD0
XX1的样子,太巧妙了。即只要加一行就可以AC啦。

*/


版权声明:题解中哪里写错请一定要指出来QwQ 转载还请注明下出处哦,谢谢^_^

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

CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) T...

hdu 5411 CRB and Puzzle(矩阵快速幂)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5411 解题思路: 题目大意: 给定n个点 常数m 下面n行第i行第一个数字表示i点的出...

hdu 5411 CRB and Puzzle 矩阵快速幂

题意:有n种数量无限的方块,每种方块后可以拼接另一个方块,但是只能拼接给定种类的方块,问最多拼接M次能拼接出多少种不同的样式。这道题中n只有50,很容易想到矩阵快速幂,毕竟这种题已经烂大街了。然而比赛...
  • CHCXCHC
  • CHCXCHC
  • 2015年08月26日 14:34
  • 290

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

CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others...

hdu 5411 CRB and Puzzle (矩阵快速幂优化dp)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5411 题意:按题目转化的意思是,给定N和M,再给出一些边(u,v)表示u和v是连通的,问走0,1,2.....
  • w20810
  • w20810
  • 2015年08月21日 15:53
  • 434

HDU 5411 CRB and Puzzle(矩阵快速幂+可达矩阵)

HDU 5411题意:Count the number of different patterns by counting the number of different paths of lengt...

HDOJ 5411 CRB and Puzzle (矩阵快速幂)

题意给出一个邻接矩阵,求走k步以内所有的路径数量。思路离散数学里面学的嘛,可达矩阵的k次方就是走k步时的可达矩阵,然后就转化成计算A+A2...AmA+A^2...A^m 然后想到了POJ的那个经典...

HDU 5414 CRB and String( 2015 Multi-University Training Contest 10)

比赛时队友有想法了我就一直在出数据了。 然而那个想法是错的。到快结束的时候才验证了是错的。 都怪自己太懒,没有验证正确性就盲目地同意队友写,然后两个人越改越乱,要多思考啊。 然后...

HDU 5407 CRB and Candies(素数筛 + 逆元 + 组合数公式)——2015 Multi-University Training Contest 10

传送门CRB and CandiesTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others...

hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)

CRB and Tree                                                             Time Limit: 8000/4000 MS (...
  • caduca
  • caduca
  • 2015年08月20日 18:17
  • 2635
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【HDU5411 2015 Multi-University Training Contest 10F】【矩阵快速幂 加一行构造法】CRB and Puzzle 矩阵的1次方到n次方的数值和
举报原因:
原因补充:

(最多只允许输入30个字)