• $TJOI$棋盘


    (TJOI)棋盘

    状压(DP)加矩阵优化。

    关于这道题的出题人。。。

    他当年应该被打死了吧。。。

    题目中的第(1)行第(k)列指的是从(0)开始标号下的第(1)行第(k)列,也就是说,这一题存在第(0)行第(0)列!

    搞什么不好,非得要搞题意理解。。。

    (f[i][j])为第(i)行,状态为(j)时的答案(我们只压了一行)。

    如果(j)可以转移到(k),则有(f[i+1][k]=f[i][j]+f[i+1][k])

    这里我们发现,两个集合是否可以转移,这是固定的,也就是说,我们可以矩阵快速幂优化一下。

    矩阵记得清零。。。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int M=7;
    const int p=1LL<<32;
    const int N=1e6+10;
    int n,m,K,C,Max,ans,f[1<<M];
    vector<int> Atk[3];
    struct Matrix
    {
    	int A[80][80];
    	inline Matrix (){ memset(A,0,sizeof(A));}
    	inline Matrix operator * (const Matrix &B) const
    		{
    			Matrix C;
    			for(register int i=0;i<Max;++i)
    				for(register int j=0;j<Max;++j)
    					for(register int k=0;k<Max;++k)
    						C.A[i][j]=(C.A[i][j]%p+(A[i][k]*B.A[k][j])%p+p)%p;
    			return C;
    		}
    } Trn;
    inline Matrix ksm(Matrix b,int k)
    {
    	Matrix a=b;k--;
    	while(k)
    	{
    		if(k&1) a=a*b;
    		b=b*b;k>>=1;
    	}
    	return a;
    }
    inline bool Check(int x,int y)
    {
    	for(register int i=0;i<m;++i)
    		if((x>>i)&1)
    		{
    			for(register int j=0;j<(int)Atk[1].size();++j)
    				if(0<=i+Atk[1][j]&&i+Atk[1][j]<m)
    					if((x>>(i+Atk[1][j]))&1) return 0;
    			for(register int j=0;j<(int)Atk[2].size();++j)
    				if(0<=i+Atk[2][j]&&i+Atk[2][j]<m)
    					if((y>>(i+Atk[2][j]))&1) return 0;
    		}
    	for(register int i=0;i<m;++i)
    		if((y>>i)&1)
    		{
    			for(register int j=0;j<(int)Atk[1].size();++j)
    				if(0<=i+Atk[1][j]&&i+Atk[1][j]<m)
    					if((y>>(i+Atk[1][j]))&1) return 0;
    			for(register int j=0;j<(int)Atk[0].size();++j)
    				if(0<=i+Atk[0][j]&&i+Atk[0][j]<m)
    					if((x>>(i+Atk[0][j]))&1) return 0;
    		}
    	return 1;
    }
    signed main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	n=read(),m=read(),C=read(),K=read();Max=1LL<<m;
    	for(register int i=0;i<3;++i)
    		for(register int j=0;j<C;++j)
    			if(read()&&(j!=K||i!=1)) Atk[i].push_back(j-K);
    	for(register int i=0;i<Max;++i)
    		for(register int j=0;j<Max;++j)
    			Trn.A[i][j]=Check(i,j);
    	for(register int i=0;i<Max;++i) f[i]=Trn.A[0][i];Trn=ksm(Trn,n);
    	for(register int i=0;i<Max;++i) ans=(ans%p+(f[i]%p*Trn.A[i][0]%p+p)%p+p)%p;
    	printf("%lld",(ans+p)%p);
    }
    
  • 相关阅读:
    运行.bat批处理,CMD窗口隐藏,并制作为EXE文件
    TinyXML:一个优秀的C++ XML解析器(转载)
    2013编程之美资格赛【传话游戏】
    linux GTK教程(消息机制/标签/按钮/图像/文本/对话框/菜单/容器)
    c++强制类型转换(总结)
    string与char*的转换(转载)
    网络数据包捕获函数库Libpcap安装与使用(非常强大)
    Linux 高级Socket编程
    linux GTK 安装
    .dll和.lib文件的生成和使用 c++
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11761352.html
Copyright © 2020-2023  润新知