• 【刷题】BZOJ 4000 [TJOI2015]棋盘


    Description

    Input

    输入数据的第一行为两个整数N,M表示棋盘大小。第二行为两个整数P,K,

    表示攻击范围模板的大小,以及棋子在模板中的位置。接下来三行,

    每行P个数,表示攻击范围的模版。每个数字后面一个空格。

    Output

    一个整数,表示可行方案Mod 2 ^32

    Sample Input

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

    Sample Output

    7

    HINT

    1<=N<=10^6,1<=M<=6

    Solution

    这题有点无聊
    先考虑把按照棋盘每一行去状压dp,然后发现跑不了
    于是又了解到每次状压的转移方程是一样的,并且 (m) 小得可怜,于是就可以用矩阵乘法优化
    预处理的话就直接暴力枚举每一个状态和下一个状态,看能否转移就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=1000000+10,MAXM=(1<<6)+10;
    int n,m,P,K,G[4],atk1,atk2;
    ui ans;
    struct Matrix{
    	ui a[MAXM][MAXM];
    	inline Matrix operator * (const Matrix &A) const {
    		Matrix B;
    		for(register int i=0;i<(1<<m);++i)
    			for(register int j=0;j<(1<<m);++j)
    			{
    				B.a[i][j]=0;
    				for(register int k=0;k<(1<<m);++k)B.a[i][j]+=a[i][k]*A.a[k][j];
    			}
    		return B;
    	};
    };
    Matrix A;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline int check(int st,int ed)
    {
    	atk1=0,atk2=0;
    	for(register int i=0;i<m;++i)
    		if(st&(1<<i))
    		{
    			if(P-K-1>=i)atk1|=(G[1]>>P-K-1-i),atk2|=(G[2]>>P-K-1-i);
    			else atk1|=(G[1]<<i-P+K+1),atk2|=(G[2]<<i-P+K+1);
    		}
    	if((atk1&st)||(atk2&ed))return 0;
    	atk1=0;atk2=0;
    	for(register int i=0;i<m;++i)
    		if(ed&(1<<i))
    		{
    			if(P-K-1>=i)atk1|=(G[1]>>P-K-1-i),atk2|=(G[0]>>P-K-1-i);
    			else atk1|=(G[1]<<i-P+K+1),atk2|=(G[0]<<i-P+K+1);
    		}
    	if((atk1&ed)||(atk2&st))return 0;
    	return 1;
    }
    inline Matrix qexp(Matrix a,int b)
    {
    	Matrix res=a;b--;
    	while(b)
    	{
    		if(b&1)res=res*a;
    		a=a*a;
    		b>>=1;
    	}
    	return res;
    }
    int main()
    {
    	read(n);read(m);read(P);read(K);
    	for(register int i=0;i<3;++i)
    		for(register int j=0,x;j<P;++j)read(x),G[i]|=(x<<P-j-1);
    	G[1]^=(1<<P-K-1);
    	for(register int i=0;i<(1<<m);++i)
    		for(register int j=0;j<(1<<m);++j)A.a[i][j]=check(i,j);
    	A=qexp(A,n);
    	for(register int i=0;i<(1<<m);++i)ans+=A.a[0][i];
    	printf("%u
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    10. 正则表达式匹配
    svn 类似.gitignore功能实现
    GF学习未解之谜
    cocos
    unity 编辑器内对Game视图进行截图
    Roughlike游戏里面的随机数种子
    网站推荐——游戏图标网
    Unity 使用image绘制线段 直线
    c# unity 异步任务队列
    Unity编辑器调用外部exe程序 和 windows文件夹
  • 原文地址:https://www.cnblogs.com/hongyj/p/9544216.html
Copyright © 2020-2023  润新知