Description

为了提高智商,ZJY去新世界旅游了。可是旅游过后的ZJY杯具的发现要打开通往原来世界的门,必须要解开门上面画的谜题。谜题是这样的:有个\(n\)行\(m\)列的棋盘,棋盘上可以放许多特殊的棋子。每个棋子的攻击范围是\(3\)行,\(p\)列。输入数据用一个\(3\times p\)的矩阵给出了棋子攻击范围的模板,棋子被默认为模板中的第\(1\)行,第\(k\)列,则棋子能攻击到的位置是\(1\),不能攻击到的位置是\(0\)。\(1\leq p\leq m,0\leq k<p\)。输入数据保证第\(1\)行第\(k\)列的位置是\(1\)。打开门的密码就是,在要求棋子互相不能攻击到的前提下,摆放棋子的方案数。注意什么棋子都不摆放也算作一种可行方案。由于方案数可能很大,而密码为\(32\)位的二进制密码,所以ZJY仅需要知道方案数对\(2^{32}\)取余数的结果即可。

Input

输入数据的第一行为两个整数\(n\)和\(m\),表示棋盘的大小。第二行为两个整数\(p\)和\(k\),表示接下来的攻击范围模板的大小,以及棋子在模板中的位置。接下来三行,每行有\(P\)个数,表示攻击范围的模版。每个数字后有一个空格。

Output

输出数据仅有一行,一个整数,表示可行的方案数模\(2^{32}\)的余数。

Range

对于\(10\%\),\(1 \leq n \leq 5,1 \leq m \leq 5\)

对于\(50\%\),\(1 \leq n \leq 1000,1 \leq m \leq 6\)

对于\(100\%\),\(1\leq n\leq 1000000,1\leq m\leq 6\)

Solution

恶心题。

被这题卡了一天。

首先注意到它的行和列是从 \(0\) 开始标号的,所以第 \(1\) 行第 \(p\) 列其实是中间一行的某一列。

预处理出所有能摆放和两行之间能转移的情况。

这里要用位运算,最开始拿数组模拟每位弄了半天还是错的,用位运算一下就出来了。

观察到转移可以用矩阵加速,于是一个矩阵快速幂敲上去就行了。

注意最后求答案矩阵的时候要新开一个数组不能直接在 \(f\) 数组上面求!

Code

#include<cstdio>
#include<cctype>
#include<cstring>
#define int unsigned long long int maxn;
int mp[5];
int n,m,p,k;
bool vis[105];
int f[70][70];
const int mod=4294967296; struct Matrix{
int a[100][100]; void clear(){
memset(a,0,sizeof a);
} void init(){
for(int i=0;i<maxn;i++)
a[i][i]=1;
} Matrix operator*(const Matrix &x)const{
Matrix z; z.clear();
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
for(int k=0;k<maxn;k++){
z.a[i][j]+=(x.a[i][k]*a[k][j])%mod;
z.a[i][j]%=mod;
}
}
}
return z;
} void print(){
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++)
printf("i=%lld,j=%lld,a=%lld\n",i,j,a[i][j]);
}
puts("");
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++)
printf("%lld",a[i][j]);
puts("");
}
}
}M; void read(int &x){
x=0; char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
} bool check(int x){
for(int i=1;i<=m;i++){
if(x&(1<<i-1)){
if(p-k+1<=i){
if((x&(mp[2]<<(i+k-p-1)))!=(1ll<<(i-1))){
//printf("x=%lld,i=%lld\n",x,i);
//printf("i-1=%lld,1<<i-1=%lld\n",i-1,1<<i-1);
//printf("i+k-p-1=%lld,mp[2]<<=%lld,x&=%lld,1<<=%lld\n",i+k-p-1,mp[2]<<i+k-p-1,x&(mp[2]<<i+k-p-1),1ll<<(i-1));
return 0;
}
}
else{
if((x&(mp[2]>>(p-k+1-i)))!=(1ll<<i-1))
return 0;
}
}
}
return 1;
} bool judge(int x,int y){
for(int i=1;i<=m;i++){
if(x&(1<<i-1)){
if(p-k+1<=i){
if((y&(mp[3]<<(i+k-p-1))))
return 0;
}
else{
if((y&(mp[3]>>(p-k+1-i))))
return 0;
}
}
if(y&(1<<i-1)){
if(p-k+1<=i){
if((x&(mp[1]<<(i+k-p-1))))
return 0;
}
else{
if((x&(mp[1]>>(p-k+1-i))))
return 0;
}
}
}
return 1;
} Matrix ksm(Matrix a,int b,int c){
Matrix ans; ans.init();
while(b){
if(b&1)
ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
} void mul(int a[70][70],int b[70][70],int c[70][70])
{
int ret[70][70];
memset(ret,0,sizeof ret);
for(int i=0;i<maxn;i++)
for(int k=0;k<maxn;k++)
for(int j=0;j<maxn;j++)
{
ret[i][j]=(ret[i][j]+a[i][k]*b[k][j]%mod)%mod;
}
memcpy(c,ret,sizeof ret);
} int a[70][70];
int ans[70][70]; void qm(int y)
{
for(int i=0;i<maxn;i++)
ans[i][i]=1;
while(y)
{
if(y&1) mul(ans,a,ans);
mul(a,a,a);
y>>=1;
}
} signed main(){
read(n),read(m),read(p),read(k); k++;
maxn=1<<m;
for(int i=1;i<=3;i++){
for(int x,j=1;j<=p;j++){
read(x);
if(x)
mp[i]|=1<<p-j;
}
}
Matrix aa; aa.clear();
for(int i=0;i<maxn;i++){
if(check(i)){
vis[i]=1,f[0][i]=1;
//printf("i=%lld\n",i);
}
}
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
if(vis[i] and vis[j]){
if(judge(i,j)){
//printf("i=%lld,j=%lld\n",i,j);
aa.a[j][i]=1;
}
}
}
}
/*for(int i=0;i<maxn;i++)
a[0][i]=a[i][0]=1;*/
//aa.print();
Matrix b=ksm(aa,n-1,mod);
int c[70][70]; memset(c,0,sizeof c);
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
for(int k=0;k<maxn;k++)
(c[i][j]+=f[i][k]*b.a[k][j])%=mod;
}
}
/*qm(n-1);
mul(f,ans,ans);*/
int sum=0;
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++)
(sum+=c[i][j])%=mod;
}
printf("%llu\n",sum%mod);
return 0;
}

[TJOI2015] 棋盘的更多相关文章

  1. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

  2. 【BZOJ4000】[TJOI2015]棋盘(矩阵快速幂,动态规划)

    [BZOJ4000][TJOI2015]棋盘(矩阵快速幂,动态规划) 题面 BZOJ 洛谷 题解 发现所有的东西都是从\(0\)开始编号的,所以状压只需要压一行就行了. 然后就可以随意矩乘了. #in ...

  3. 【刷题】BZOJ 4000 [TJOI2015]棋盘

    Description Input 输入数据的第一行为两个整数N,M表示棋盘大小.第二行为两个整数P,K, 表示攻击范围模板的大小,以及棋子在模板中的位置.接下来三行, 每行P个数,表示攻击范围的模版 ...

  4. BZOJ4000 [TJOI2015]棋盘

    首先是状态压缩DP... 然后我们发现转移都是一样的...可以矩阵优化... 于是做完啦QAQQQ 题目读不懂?恩多读几遍就读懂了,诶诶诶!别打我呀! /*********************** ...

  5. BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)

    显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...

  6. [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)

    题意极其有毒,注意给的行列都是从0开始的. 状压DP,f[i][S]表示第i行状态为S的方案数,枚举上一行的状态转移.$O(n2^{2m})$ 使用矩阵加速,先构造矩阵a[S1][S2]表示上一行为S ...

  7. BZOJ4000 [TJOI2015]棋盘 【状压dp + 矩阵优化】

    题目链接 BZOJ4000 题解 注意题目中的编号均从\(0\)开始= = \(m\)特别小,考虑状压 设\(f[i][s]\)为第\(i\)行为\(s\)的方案数 每个棋子能攻击的只有本行,上一行, ...

  8. TJOI2015 day2解题报告

    TJOI2015终于写完啦~~~ T1:[TJOI2015]旅游 描述:(BZ没题面只能口述了..)一个人在一棵树上走,每次从a->b会进行一次贸易(也就是在这条路径上买入物品然后在后面卖出)然 ...

  9. [暑假的bzoj刷水记录]

    (这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊  堆一起算了 隔一段更新一下.  7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...

随机推荐

  1. 十大ios开发者喜爱的开源库

    十大ios开发者喜爱的开源库 (转自博客园) 2014-08-17 14:07:58|  分类: objective-c |  标签:ios  开源库  |举报|字号 订阅 下载LOFTER我的照片书 ...

  2. obj-c编程01[扩展学习01]:对象消息机制工作原理

    obj-c中的类就像C语言中的struct.NSObject类声明一个成员变量isa,因为NSObject类是整个继承树的根,所以每个类中都有一个isa其指向创建的对象.在类结构中有实例变量(成员变量 ...

  3. python 网络框架twisted基础学习及详细讲解

    twisted网络框架的三个基础模块:Protocol, ProtocolFactory, Transport.这三个模块是构成twisted服务器端与客户端程序的基本.Protocol:Protoc ...

  4. javascript简单介绍(二)

    晨读单词: onmouseover:鼠标移入 onmouseout:鼠标移出 attribute:属性 node:节点 document:文档 element:元素 textNode:文本节点 app ...

  5. Python中的函数与变量

    本节内容 函数的定义方法 函数功能 函数的返回值 函数的形参与实参 全局变量与局部变量 递归 函数的作用域 匿名函数lambda 函数式编程 常用内置函数 其他内置函数 函数 函数的定义方法 函数就相 ...

  6. git如何移除某文件夹的版本控制

    目录结构如下 project bin lib src ...... 执行如下的操作 git add . git commit -m "add bin/ lib/ src/" git ...

  7. 学习spring中遇见的问题

    报错: Unexpected exception parsing XML document from class path resource [applicationContext.xml]; nes ...

  8. HTML5这个概念的解释

    关于HTML5这个概念我一直很多困惑,稍微总结一下. 从HTML说起,HTML作为一个标记语言,通过这种标记定义了一个网页的dom tree,也定义了网页的结构,然后CSS定义了在这个结构基础上的样式 ...

  9. Caffe 编译后 make runtest 出现locale::facet::_S_create_c_locale 错误

    You might need to append LC_ALL="en_US.UTF-8" to file: /etc/default/locale and reboot your ...

  10. csrf攻击与防范

    CSRF(Cross Site Request Forgeries)跨网站请求伪造,也叫XSRF,通过伪装来自受信任用户的请求来攻击利用受信任网站. 与对比 xss:本网站运行了来自其它网站的脚本 c ...