$n \leq 17,m \leq 17$,$n*m$的01矩形,对每一个0问:当他单独变成1之后,在其他0处放多米诺牌(不一定放满,可以不放)的方案数。膜$1e9+7$。

直接$dp$是$n^42^n$,很难受。这种整体挖一块的东西可以用拼接法,就是用那一块前的$dp$值和那一块后的$dp$值计算答案。

$f(i,j,k)$--从$(1,1)$到$(i,j)$,在$(i,j)$前面$m$个格子状态$k$的方案数,$g(i,j,k)$--从$(n,m)$到$(i,j)$,在$(i,j)$后面$m$个格子状态$k$的方案数。状态$k$中1表示这一位是障碍或放了牌,0表示还没放。

然后来看$f(i,j,k)$和$g(i,j,k)$怎么合并出$(i,j)$的答案。画画图可以发现,$f(i,j,p)$和$g(i,j,q)$可以合并,除非他们空出的地方刚好对齐可以放竖的多米诺,表现为:$p,q$的第一位都是1,然后$p$和$q$的后$m-1$位恰好相反。因此可以$O(2^m)$算出一个点的答案。总复杂度$n^22^n$。

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
//#include<math.h>
//#include<queue>
//#include<vector>
#include<algorithm>
//#include<iostream>
//#include<assert.h>
using namespace std; int n,m;
const int mod=1e9+;
int g[][][],f[][],cur;
bool mp[][]; int rev(int x) {int ans=x&; for (int i=;i<m;i++) ans|=((x>>i)&)<<(m-i); return ans;} int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) for (int j=,x;j<=m;j++) scanf("%d",&x),mp[i][j]=x; g[n][m][(<<m)-]=;
for (int i=n;i;i--)
for (int j=m;j;j--)
{
int ni=i,nj=j-; if (nj==) ni=i-,nj=m; if (ni==) break;
for (int k=,nk;k<(<<m);k++) if (g[i][j][k])
{
if ((k&)== && i<n && !mp[i+][j])
{if (!mp[i][j]) {nk=(k>>)|(<<(m-)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:;}}
else
{
nk=(k>>)|(<<(m-)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:;
if (!mp[i][j])
{
nk=(k>>); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:;
if (j<m && ((k>>(m-))&)== && !mp[i][j+])
{nk=(k>>)|(<<(m-))|(<<(m-)); g[ni][nj][nk]+=g[i][j][k],g[ni][nj][nk]-=g[ni][nj][nk]>=mod?mod:;}
}
}
}
} cur=; f[][(<<m)-]=;
for (int i=;i<=n;i++,puts(""))
for (int j=;j<=m;j++)
{
int ans=;
if (!mp[i][j])
for (int k=;k<(<<m);k+=) ans+=1ll*f[cur][k]*g[i][j][rev(k)]%mod,ans-=ans>=mod?mod:;
printf("%d ",ans);
int ni=i,nj=j+; if (nj>m) ni++,nj=; if (ni>n) break;
for (int k=,nk;k<(<<m);k++) if (f[cur][k])
{
if ((k&)== && i> && !mp[i-][j])
{if (!mp[i][j]) {nk=(k>>)|(<<(m-)); f[cur^][nk]+=f[cur][k],f[cur^][nk]-=f[cur^][nk]>=mod?mod:;}}
else
{
nk=(k>>)|(<<(m-)); f[cur^][nk]+=f[cur][k],f[cur^][nk]-=f[cur^][nk]>=mod?mod:;
if (!mp[i][j])
{
nk=(k>>); f[cur^][nk]+=f[cur][k],f[cur^][nk]-=f[cur^][nk]>=mod?mod:;
if (j> && ((k>>(m-))&)== && !mp[i][j-])
{nk=(k>>)|(<<(m-))|(<<(m-)); f[cur^][nk]+=f[cur][k],f[cur^][nk]-=f[cur^][nk]>=mod?mod:;}
}
}
f[cur][k]=;
}
cur^=;
}
return ;
}

话说这代码调了好久的。。是个小错误,以后调代码得静下心了。

「CodePlus 2018 3 月赛」白金元首与莫斯科的更多相关文章

  1. 【LibreOJ】#6299. 「CodePlus 2018 3 月赛」白金元首与克劳德斯

    [题意]给出坐标系中n个矩形,类型1的矩形每单位时间向x轴正方向移动1个单位,类型2的矩形向y轴正方向,初始矩形不重叠,一个点被矩形覆盖当且仅当它在矩形内部(不含边界),求$(-\infty ,+\i ...

  2. 「CodePlus 2018 3 月赛」白金元首与克劳德斯

    所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重 ...

  3. [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞

    [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...

  4. 【LibreOJ】#6259. 「CodePlus 2017 12 月赛」白金元首与独舞

    [题目]给定n行m列的矩阵,每个位置有一个指示方向(上下左右)或没有指示方向(任意选择),要求给未定格(没有指示方向的位置)确定方向,使得从任意一个开始走都可以都出矩阵,求方案数.n,m<=20 ...

  5. 「CodePlus 2017 12 月赛」白金元首与独舞

    description 题面 data range \[ 1 \leq T \leq 10, 1 \leq n, m \leq 200 , 0 \leq k \leq \min(nm, 300)\] ...

  6. 走进矩阵树定理--「CodePlus 2017 12 月赛」白金元首与独舞

    n,m<=200,n*m的方阵,有ULRD表示在这个格子时下一步要走到哪里,有一些待决策的格子用.表示,可以填ULRD任意一个,问有多少种填法使得从每个格子出发都能走出这个方阵,答案取模.保证未 ...

  7. loj6259「CodePlus 2017 12 月赛」白金元首与独舞

    分析 我们将没连的点连向周围四个点 其余的按照给定的方向连 我们将所有连出去的位置统一连到0点上 再以0作为树根 于是就将问题转化为了有向图内向树计数 代码 #include<iostream& ...

  8. 【LibreOJ】#6354. 「CodePlus 2018 4 月赛」最短路 异或优化建图+Dijkstra

    [题目]#6354. 「CodePlus 2018 4 月赛」最短路 [题意]给定n个点,m条带权有向边,任意两个点i和j还可以花费(i xor j)*C到达(C是给定的常数),求A到B的最短距离.\ ...

  9. @loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C ...

随机推荐

  1. for循环输出i为同一值的问题

    使用闭包将变量i的值保护起来. //sava1:加一层闭包,i以函数参数形式传递给内层函数 for( var i=0; i<ps.length; i++ ) { (function(arg){ ...

  2. 用cssText批量修改样式

    一般情况下我们用js设置元素对象的样式会使用这样的形式: var element= document.getElementById(“id”);element.style.width=”20px”;e ...

  3. CPP-网络/通信:COM

    ))//打开串口 { ) { CloseCom();//关闭串口 break; } //添加处理代码. } //最后关闭串口 CloseCom();//关闭串口

  4. chosen选择框加载数据

    1.单选$(select).val($("#id").val());$(select).trigger("chosen:updated"); 2.多选 func ...

  5. commons-logging 和log4j包下载 Spring根据XML配置文件生成对象

    需要用到Spring压缩包中的四个核心JAR包 beans .context.core 和expression 下载地址: https://pan.baidu.com/s/1qXLHzAW 以及日志j ...

  6. C# 使用Epplus导出Excel [3]:合并列连续相同数据

    C# 使用Epplus导出Excel [1]:导出固定列数据 C# 使用Epplus导出Excel [2]:导出动态列数据 C# 使用Epplus导出Excel [3]:合并列连续相同数据 C# 使用 ...

  7. 博弈论入门 Bash 、Nim 、Wythoff's Game结论及c++代码实现

    SG函数先不说,给自己总结下三大博弈.和二进制及黄金分割联系密切,数学真奇妙,如果不用考试就更好了. 1.Bash Game:n个物品,最少取1个,最多取m个,先取完者胜. 给对手留下(m+1)的倍数 ...

  8. UVa 167(八皇后)、POJ2258 The Settlers of Catan——记两个简单回溯搜索

    UVa 167 题意:八行八列的棋盘每行每列都要有一个皇后,每个对角线上最多放一个皇后,让你放八个,使摆放位置上的数字加起来最大. 参考:https://blog.csdn.net/xiaoxiede ...

  9. Go统计键盘输入随机字母的个数

    package main import "fmt" //通过键盘输入20个小写字母,统计个数 func main(){ //通过键盘器获取字符 var arr [20]byte f ...

  10. python--线程的其他方法

    一 . current_thread的用法 import threading import time from threading import Thread, current_thread def ...