「JOISC 2016 Day 1」棋盘游戏
「JOISC 2016 Day 1」棋盘游戏
先判无解:第1,3行有连续的空格或四个角有空格。
然后可以发现有解的情况第1,3行可以在任意时间摆放。
对于某一列,若第2行放有棋子,那么显然可以把棋盘分开两边来计算,然后再排列一下。
所以目前要处理的是一段 第二行都没有棋子的棋盘的方案数。
对于该段棋盘:
定义\(dp[i][j][2]\)为前\(i\)列,当前列的第二行是第\(j\)个放置的,\(0/1\)表示是否为通过行的方式放置。
这里为了避免重复和方便,若可以通过列的方式放置,就不通过行的方式放置。
具体的转移相当于前\(i-1\)列放置棋子的顺序序列中插入第\(i\)列的放置顺序。
第一列在dp前处理掉。
转移就分为3种(显然两列不能同时通过行的方式放置)。
令v为\(i\)列中1,3行没放置棋子格子数。
以T来指代\(i\)列第二行的棋子,\(T_1\)为\(i-1\)列第二行棋子。
0->0
只需要保证在放T前放好v。
0->1
要保证在放T后才放好v,\(T_1\)在T前放。
1->0
保证在放T前放好v,放T在\(T_1\)前。
整个棋盘的第一和最后一列都是不用特判的,因为它们都是列放置。
对于其他整段,第一列的第二行前面和最后一列的第二行后面都是有棋子的。
#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r) {
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
const int mn=2005;
int dp[mn][mn*3][2];
int had[mn][4],n;//其实这里had是没有的意思,没有改过来
const int mod=1e9+7;
int mul[mn*3],inv[mn*3];
int C(int a,int b){
return 1LL*mul[b]*inv[a]%mod*inv[b-a]%mod;
}
int A(int a,int b){
return 1LL*mul[b]*inv[b-a]%mod;
}
int tot_sum,ans=1;
void add(int &a,long long b){
a=(a+b)%mod;
}
int Sum[mn*3][2];
void get_ans(int l,int r){
if(l>r)return;
int sum=0;
int v=had[l][1]+had[l][3];
dp[l][v+1][0]=A(v,v);
rep(q,1,v)dp[l][q][1]=A(v,v);
sum+=v+1;
rep(q,l+1,r){
v=had[q][1]+had[q][3];
rep(w,1,sum)Sum[w][0]=dp[q-1][w][0],Sum[w][1]=dp[q-1][w][1];
rep(w,1,sum)add(Sum[w][0],Sum[w-1][0]),add(Sum[w][1],Sum[w-1][1]);
rep(w,v+1,sum+v+1){
add(dp[q][w][0],1LL*A(v,w-1)*Sum[sum][0]);
// rep(e,1,sum){
// add(dp[q][w][0],1LL*A(v,w-1)*dp[q-1][e][0]);
// }
}
rep(w,v+1,sum+v){
add(dp[q][w][0],1LL*A(v,w-1)*(Sum[sum][1]-Sum[w-v-1][1]));
// rep(e,w-v,sum){
// add(dp[q][w][0],1LL*A(v,w-1)*dp[q-1][e][1]);
// }
}
rep(r,0,v-1){
int ty=C(r,v);
rep(w,r+1,sum+r+1){
add(dp[q][w][1],1LL*ty*A(r,w-1)*A(v-r,sum+v+1-w)%mod*Sum[w-r-1][0]);
// rep(e,0,w-r-1){
// add(dp[q][w][1],1LL*ty*A(r,w-1)*dp[q-1][e][0]%mod*A(v-r,sum+v+1-w));
// }
}
}
sum+=v+1;
}
int tot=0;
rep(q,0,sum){
add(tot,dp[r][q][0]);
add(tot,dp[r][q][1]);
}
tot_sum+=sum,ans=1LL*ans*tot%mod*C(sum,tot_sum)%mod;
}
bool check_it_can_be_solve(){
if(had[1][1]||had[1][3]||had[n][1]||had[n][3])return 0;
rep(q,2,n)if(had[q][1]&&had[q-1][1]||had[q][3]&&had[q-1][3])return 0;
return 1;
}
char as[mn];
int main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
in(n);
mul[0]=1;
rep(q,1,n*3)mul[q]=1LL*mul[q-1]*q%mod;
inv[0]=inv[1]=1;
rep(q,2,n*3)inv[q]=1LL*(mod-mod/q)*inv[mod%q]%mod;
rep(q,1,n*3)inv[q]=1LL*inv[q-1]*inv[q]%mod;
rep(q,1,3){
scanf("%s",as+1);
rep(w,1,n)had[w][q]=as[w]=='x';
}
if(!check_it_can_be_solve()){
puts("0");
return 0;
}
int now=1;
while(now<=n&&had[now][2])++now;
if(now==n+1)get_ans(1,now-1);
else{
get_ans(1,now-1);
int v=had[now][1]+had[now][3];
tot_sum+=v,ans=1LL*ans*A(v,tot_sum)%mod;
++now;
while(1){
int last=now;
while(now<=n&&had[now][2])++now;
if(now==n+1)get_ans(last,now-1);
else{
get_ans(last,now-1);
v=had[now][1]+had[now][3];
tot_sum+=v,ans=1LL*ans*A(v,tot_sum)%mod;
++now;
}
if(now==n+1)break;
}
}
printf("%d\n",(ans+mod)%mod);
return 0;
}
「JOISC 2016 Day 1」棋盘游戏的更多相关文章
- Loj #2731 「JOISC 2016 Day 1」棋盘游戏
Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...
- LOJ #2731. 「JOISC 2016 Day 1」棋盘游戏(dp)
题意 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少有一个棋子,也至少有一个空位. 游戏的目标是:在还没有放棋 ...
- LOJ 2737 「JOISC 2016 Day 3」电报 ——思路+基环树DP
题目:https://loj.ac/problem/2737 相连的关系形成若干环 / 内向基环树 .如果不是只有一个环的话,就得断开一些边使得图变成若干链.边的边权是以它为出边的点的点权. 基环树的 ...
- LOJ 2736 「JOISC 2016 Day 3」回转寿司 ——堆+分块思路
题目:https://loj.ac/problem/2736 如果每个询问都是 l = 1 , r = n ,那么每次输出序列的 n 个数与本次操作的数的最大值即可.可以用堆维护. 不同区间的询问,可 ...
- loj2734「JOISC 2016 Day 2」女装大佬 || 洛谷P3615 如厕计划
loj2734 洛谷P3615 http://218.5.5.242:9021/problem/185 不会做... 题解(来自ditoly): 这一步更详细的解释(来自kkksc03): 还是从后面 ...
- 「JOISC 2016 Day 3」回转寿司
https://loj.ac/problem/2736 题解 挺有意思的题. 考虑这种操作不好直接维护,还有时限比较长,所以考虑分块. 考虑一个操作对整个块的影响,无非就是可能把最大的拿走,再把新的元 ...
- [LOJ#2732] 「JOISC 2016 Day 2」雇佣计划
参考博文 (不过个人感觉我讲的稍微更清楚一点) 题目就是让我们求图中满足数值大于等于B的连通块数量 然后我们可以尝试转换为求连通块两端所产生的“谷”的数量,显然一个连通块对谷可以贡献2的答案,最终答案 ...
- 题解 「JOISC 2016 Day 3」电报
题目传送门 题目大意 给出一个\(n\)个点\(n\)条边的图,每个点有且仅有一个出边,改变每条边都会有对应的花费.求最小的花费使得整个图强连通. 思路 很显然,最后的图就是一个环.那我们要求的答案实 ...
- 「JOISC 2015 Day 1」卡片占卜
题目描述 K 理事长是占卜好手,他精通各种形式的占卜.今天,他要用正面写着 I ,背面写着 O 的卡片占卜一下日本 IOI 国家队的选手选择情况. 占卜的方法如下: 首先,选取五个正整数 A,B,C, ...
随机推荐
- 小白自制Linux开发板(第二季 V3s篇) 一. 换个核心再来一次
1.前言 大家心心念念(个人认为)的小白自制开发板全新系列正式来了,之前我们使用全志的F1C200s芯片制作了一个小电脑,众所周知,调试很艰难,坑也很多,以至于墨云到现在还是没找到对应的补救方案,为了 ...
- Unsupervised Domain Adaptation by Backpropagation
目录 概 主要内容 代码 Ganin Y. and Lempitsky V. Unsupervised Domain Adaptation by Backpropagation. ICML 2015. ...
- JVM垃圾收集器专题
垃圾收集器:利用垃圾收集算法,实现垃圾回收的实践落地. 1 HotSpot垃圾回收器 HotSpot垃圾回收器有多个,可以配合使用. 1.1 垃圾回收的一些术语 术语: Stop the world ...
- 【odoo】关于odoo二开模块规范的一点思考
老韩头的开发日常 ☞ [好书学习]系列 背景 作为丙方,完成了甲方的二开需求.因此,在设计二开模块的时候,考虑的是当时所列的需求清单,并整合到一个二开模块中.完成交付后,客户评价蛮好的.因此,成功的为 ...
- 在pycharm中创建py文件——创建你的第一个项目
开启编程第一步 创建一个项目 创建项目了xdm,敲黑板了哈 首先打开你的pycharm,点击New Project新建项目 就会进入到配置你这个项目所要用到的环境,这里我们用python列举 在L ...
- NIO【同步非阻塞io模型】关于 文件io 的总结
1.前言 这一篇随笔是写 NIO 关于文件输入输出的总结 /* 总结: 1.io操作包括 socket io ,file io ; 2.在nio模型,file io使用fileChannel 管道 , ...
- java单元测试调用mybatis接口并执行
今天想使用单元测试类,存储一些数据到mysql,可是,一直在报错,org.springframework.beans.factory.NoSuchBeanDefinitionException: No ...
- 接口神器之 Json Server 详细指南
简介 json-server 是一款小巧的接口模拟工具,一分钟内就能搭建一套 Restful 风格的 api,尤其适合前端接口测试使用. 只需指定一个 json 文件作为 api 的数据源即可,使用起 ...
- Bootstrap实战 - 响应式布局
一.介绍 响应式布局就是一个网站能够兼容多个终端,而不是为每个终端做一个特定的版本.这个概念是为解决移动互联网浏览而诞生的. 导航栏与轮播在大部分网站的头部占很高的比重,特别是导航栏,扮演着网站地图的 ...
- Linux环境下的Docker的安装和部署、学习-一
CentOS Docker 安装Docker支持以下的CentOS版本:CentOS 7 (64-bit)CentOS 6.5 (64-bit) 或更高的版本 前提条件目前,CentOS 仅发行版本中 ...