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

题目链接

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;
}


你可能感兴趣的:(动态规划,ACM,状态压缩dp,矩阵优化)