TJOI2015 棋盘

Description

 

Input

Output

 

Sample Input

2 2
3 1
0 1 0
1 1 1
0 1 0

Sample Output

7
 

Data Constraint

 

这题有个巨坑的地方,棋子在第1行,每k列,行和列都是从0开始编号的!!!也就是实际是第2行,第k+1列!!!

看出来后就一大水题了。

经过转换可以使得每个棋子都只影响下一行,又由于列只有6,所以用状压解

f[i][[j]表示每i行状态为j的方案,然后我们发现每2行之间的转移是一样的,所以可以预处理转移矩阵,再矩乘加快速幂优化即可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
typedef unsigned int ui;

vector<int> lim[4];

struct Matrix{
    ui a[65][65];
}pc,d;

ui ans;
ui f[1011];
int i,j,k,p,m,nj,l,n,L,sy;
int a[4][10];

Matrix operator *(Matrix a,Matrix b)
{
    Matrix c;
    memset(c.a,0,sizeof(c.a));
    int i,j,k;
    for(i=0;i<(1<<m);i++)
        for(k=0;k<(1<<m);k++)if(a.a[i][k]){
            for(j=0;j<(1<<m);j++)c.a[i][j]+=a.a[i][k]*b.a[k][j];
        }
    return c;
}

Matrix mi(Matrix a,int z)
{
    Matrix l;
    bool pz;
    int i,j;
    pz=true;
    while(z){
        if(z%2==1){
            if(pz){
                pz=false;
                for(i=0;i<(1<<m);i++)
                    for(j=0;j<(1<<m);j++)l.a[i][j]=a.a[i][j];
            }
            else l=l*a;
        }
        a=a*a;
        z/=2;
    }
    return l;
}

bool check(int ls,int ts)
{
    int i,j,sy,k;
    for(i=0;i<m;i++)if((ls&(1<<i))){
        for(j=0;j<lim[3].size();j++){
            k=lim[3][j];
            sy=i+1+k-L;
            if(sy>0&&sy<=m){
                if((ts&(1<<(sy-1))))return false;
            }
        }
    }
    for(i=0;i<m;i++)if((ts&(1<<i))){
        for(j=0;j<lim[2].size();j++){
            k=lim[2][j];
            sy=i+1+k-L;
            if(sy>0&&sy<=m){
                if(sy!=i+1&&(ts&(1<<(sy-1))))return false;
            }
        }
    }
    return true;
}

int main()
{
    scanf("%d%d",&n,&m);
    scanf("%d%d",&p,&L);
    L++;
    for(i=1;i<=3;i++)
        for(j=1;j<=p;j++){
            scanf("%d",&a[i][j]);
            if(a[2][j])lim[2].push_back(j);
            if(a[3][j])lim[3].push_back(j);
        }
    for(i=1;i<=p;i++)if(a[1][i]){
        sy=L+L-i;
        lim[3].push_back(sy);
    }
    for(i=0;i<(1<<m);i++)
        for(j=0;j<(1<<m);j++)if(check(i,j))pc.a[i][j]=1;
    d=mi(pc,n);
    for(i=0;i<(1<<m);i++)if(pc.a[0][i])f[i]++;
    for(i=0;i<(1<<m);i++)ans+=f[i]*d.a[i][0];
    printf("%u
",ans);
}
原文地址:https://www.cnblogs.com/applejxt/p/4475539.html