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. obj-c中-fobjc-arc-exceptions的解释

    在开启ARC之后正常情况下一切和内存有关的申请和释放操作皆不用你关心了,ARC全全帮你包办了.但是还有极少数的情况下,编译器无法为你生成合适的ARC额外代码,比如obj-c异常就是这么一个例子. 话句 ...

  2. unix下各种查看“变量”的命令比较

    子程序只会继承父程序的环境变量,而不继承其自定义变量. env 查看所有环境变量 set 查看所有变量,包括环境变量和自定义变量 set 还可以给程序位置参数赋值: set 1 2 3 将1赋值给$1 ...

  3. 和菜鸟一起学linux之常见错误的解决和常用命令

    1.错误提示:make:警告:检测到时钟错误.您的创建可能是不完整的. 解决方法:当前编译目录下,命令行输入:find . -type f -exec touch {} \; 2.SSH生成密钥:ss ...

  4. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  5. JS(API-日期和math)

    JS(日期和math) 问题1.获取 2017-06-10 结果: 1.dt.getMonth() + 1 是真实的月份 2.month = '0' + month 中,month 是数字(numbe ...

  6. treeview树(利用数据表实现)带展开

    Private Sub Form_Load()'引用C:\windows\system32\MSCOMCTL.OCX,否则提示出错. Dim Rec As New ADODB.Recordset Di ...

  7. mysql cluster部署

    一.mysql cluster的基本概念 1.mysql cluster的组成            管理(MGM)节点:这类节点的作用是管理MySQL Cluster内的其他节点,如提供配置数据.启 ...

  8. Python--简单接口测试实例(一)

    适用人员:初学python的测试人员,若对抓包不太清楚的可先学习抓包的知识 接口测试流程:发送请求-->返回响应-->结果判定-->生成报告 案例:下面以[今目标]新建客户为例来进行 ...

  9. Entity Framework分页扩展

    Entity Framework分页在我初入门时总是困扰这我,无论是SQL分页还是Entity Framework的分页,总是显得那么麻烦,因此对于Entity Framework单独封装了分页. 一 ...

  10. JSF-受管Bean与EL表达式

    受管Bean与EL表达式 1)编写Bean:①有一个不带形参的构造方法 ②getXxx.setXxx ③一般要实现io.Serializable接口 2)声明受管Bean:①bean名称为外界访问其属 ...