您的位置:首页 > 其它

SCU 4430 lovd_kd's_room (动态规划+矩阵优化)

2015-04-10 10:24 211 查看
题目链接

4430: lovd_kd's_room

Submit your solution

Discuss this problem
Best solutions
Time Limit: 1000ms

Description

Love_kd and mrxy56 are having a quarrel about how to decorate their marriage room. As we all know, they are both fantastic programmers,so they bought a fantastic marriage room. The room is four_grid wide and n_grid long . They have only one kind of floor tile
which is 1*2. But they don't know how to tile it.So they decide find all the ways which can tile the floor and which is the best one.(because of the large answer, please output the answer modulo M).

Input

The first line is a integer k represent this question has k test cases.Each test case consists of two integers, N (1<=N<=10^9)and M (0<M<=10^5), respectively.

Output

For each test case, output the answer modules M .

Sample Input

3
1 10000
2 10000
5 10000

Sample Output

1
5
95

Author

laobi

题意:4*n的矩形,用1*2的矩形来填,问有多少种方式可以将其填满?

题解:容易想到状压dp。用dp[i][j] 表示前i-1行已经填满,第 i 的填的状态为 j 的方案数。由于n的范围很大,所以要用到矩阵优化。

这里有一个知识点:如果一个图用一个n*n的矩阵表示,a[i][j] 表示点i到点j的边数。那么这个矩阵求x幂后,a[i][j]表示从点i到点j ,经过x条边有多少种走法?

所以这里我们根据转移方程,建一个16*16的矩阵,如果i状态能转移到j状态则a[i][j]=1。那么对于这个矩阵求n次幂后,a[15][15]就是最后的答案。

代码如下:

#include<cstdio>
#include<cstring>
#include<set>
#include<iostream>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<cctype>
#include<algorithm>
#define inf 0x3fffffff
#define nn 1100
#define mod 1000000007
typedef long long LL;
using namespace std;
int n,m;
struct Matrix
{
LL a[20][20];
int n1,n2;
void init()
{
n1=n2=16;
memset(a,0,sizeof(a));
}
Matrix operator * (const Matrix &b)const
{
Matrix tmp;
tmp.init();
tmp.n1=n1,tmp.n2=b.n2;
for(int i=0;i<n1;i++)
{
for(int j=0;j<b.n2;j++)
{
for(int k=0;k<n2;k++)
{
tmp.a[i][j]+=a[i][k]*b.a[k][j];
tmp.a[i][j]%=m;
}
}
}
return tmp;
}
}dw,tem,ans;
void init()
{
dw.init();
int i,j,k;
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
{
dw.a[i][j]=i==j?1:0;
}
}
tem.init();
int ix;
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
{
if((i^j)==15)
{
tem.a[i][j]=1;
}
else
{
if((i|j)==15)
{
ix=i&j;
for(k=0;k<4;k++)
{
if((1<<k)&ix)
{
if((1<<(k+1)&ix))
{
k++;
}
else
break;
}
}
if(k>=4)
{
tem.a[i][j]=1;
}
}
}
}
}
}
Matrix po(Matrix x,int y)
{
Matrix re=dw;
while(y)
{
if(y%2)
{
re=re*x;;
}
x=x*x;
y/=2;
}
return re;
}
int main()
{
int t;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ans=po(tem,n);
printf("%lld\n",ans.a[15][15]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: