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

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5411

题意:按题目转化的意思是,给定N和M,再给出一些边(u,v)表示u和v是连通的,问走0,1,2.....M步的方案数。

分析:这题和 hdu5318 The Goddess Of The Moon差点儿相同,就是多了一个等比数列求和

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int mod = 2015;
int N,M;
struct Matrix
{
	int M[55][55];
	Matrix(){memset(M,0,sizeof(M));}
}U,P;

Matrix Add(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			ret.M[i][j]=(a.M[i][j]+b.M[i][j])%mod;
	return ret;
}

Matrix Multi(const Matrix &a,const Matrix &b)
{
	Matrix ret;
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=N;j++)
		{
			for(int k=1;k<=N;k++)
				ret.M[i][j]+=a.M[i][k]*b.M[k][j];
			ret.M[i][j]%=mod;
		}
	}
	return ret;
}
Matrix Pow(Matrix f,int n)  //f^n,U为单位矩阵 
{
	Matrix ret=U;
	while(n)
	{
		if(n&1)
			ret=Multi(ret,f);
		n>>=1;
		f=Multi(f,f);
	}
	return ret;
}

Matrix solve(int n) //等比数列求和
{
	if(n==1)
		return P;
	Matrix temp=solve(n>>1);
	if(n&1)
	{
		Matrix t=Pow(P,n/2+1);
		return Add(Add(Multi(temp,t),temp),t);
	}
	else
		return Add(temp,Multi(temp,Pow(P,n>>1)));
}

int main()
{
	int ncase,i,j,k,x;
	for(i=0;i<55;i++)
		U.M[i][i]=1;
	scanf("%d",&ncase);
	while(ncase--)
	{
		scanf("%d%d",&N,&M);
		memset(P.M,0,sizeof(P.M));
		for(i=1;i<=N;i++)
		{
			scanf("%d",&k);
			while(k--)
			{
				scanf("%d",&x);
				P.M[i][x]=1;
			}
		}
		if(M==1)
		{
			printf("%d
",N+1);
			continue ;
		}
		Matrix temp=solve(M-1);
		int ans=N+1;
		for(i=1;i<=N;i++)
			for(j=1;j<=N;j++)
				ans+=temp.M[i][j];
		printf("%d
",ans%mod);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/gccbuaa/p/7391495.html