题目链接

https://loj.ac/problem/2731

题解

首先一个很自然的思路是,设$dp[i][j]$表示选了前$i$列,第$2$行第$i$列的格子是第$j$个被填上的。
还要加个第三维$0/1$,表示第$2$行第$i$列不是/是这一列最后一个被填上的(这决定了它是被上下填上还是被左右填上)。
转移: 若第$2$行第$i$列是棋子,则所有的都转移到$f[i][0][0]$.
(1) $0\rightarrow 0$, 两个互不影响,可以从任意的$j'$的$f[i][j'][0]$转移过来,组合数选出顺序。
(2) $1\rightarrow 0$, $(2,i)\(要在\)(2,i-1)$之前选,可以从大于当前的$j'$转移过来,同样用组合数选出顺序。
(3) $0\rightarrow 1$, $(2,i)\(要在\)(2,i-1)\(之后选。但是这里要求\)(2,i)\(早于\)(1,i)\(和\)(3,i)\(中的至少一个,因此需要分类讨论。我的代码里第一个转移是\)(2,i)\(比上下两个(如果存在)都晚,第二个转移是\)(2,i)$早于上下两个中的一个。

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
using namespace std; const int N = 2000;
const int P = 1e9+7;
char a[3][N+3];
llong dp[N+3][N*3+3][2];
llong fact[N*3+3],finv[N*3+3];
int n; llong quickpow(llong x,llong y)
{
llong cur = x,ret = 1ll;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
cur = cur*cur%P;
}
return ret;
} void updsum(llong &x,llong y) {x = (x+y)%P;} int main()
{
fact[0] = 1ll; for(int i=1; i<=N*3; i++) fact[i] = fact[i-1]*i%P;
finv[N*3] = quickpow(fact[N*3],P-2); for(int i=N*3-1; i>=0; i--) finv[i] = finv[i+1]*(i+1)%P;
scanf("%d",&n);
for(int i=0; i<=2; i++) scanf("%s",a[i]+1);
if(a[0][1]=='x'||a[0][n]=='x'||a[2][1]=='x'||a[2][n]=='x') {puts("0"); return 0;}
for(int i=2; i<=n; i++) {if((a[0][i]=='x'&&a[0][i-1]=='x')||(a[2][i]=='x'&&a[2][i-1]=='x')) {puts("0"); return 0;}}
int sum = a[1][1]=='x'?1:0;
dp[1][sum][0] = 1ll;
for(int i=2; i<=n; i++)
{
for(int j=1; j<=sum; j++) {updsum(dp[i-1][j][0],dp[i-1][j-1][0]),updsum(dp[i-1][j][1],dp[i-1][j-1][1]);}
int now = (a[0][i]=='x')+(a[2][i]=='x'); sum += now+(a[1][i]=='x');
if(a[1][i]=='o')
{
dp[i][0][0] = (dp[i-1][sum-now][0]+dp[i-1][sum-now][1])*fact[sum]%P*finv[sum-now]%P;
continue;
}
for(int j=1; j<=sum; j++)
{
if(j-now-1>=0)
{
updsum(dp[i][j][0],(dp[i-1][sum-now-1][1]-dp[i-1][j-now-1][1]+dp[i-1][sum-now-1][0]+P)*fact[j-1]%P*finv[j-now-1]%P);
}
if(now>=1)
{
updsum(dp[i][j][1],dp[i-1][min(j-1,sum-now-1)][0]*fact[sum-j]%P*finv[sum-j-now]);
if(now==2&&j>=2) {updsum(dp[i][j][1],dp[i-1][j-2][0]*(sum-j)%P*(j-1)*2ll%P);}
}
// printf("dp[%d][%d]=(%lld,%lld)\n",i,j,dp[i][j][0],dp[i][j][1]);
}
}
llong ans = 0ll;
for(int i=0; i<=sum; i++) ans = (ans+dp[n][i][0])%P;
printf("%lld\n",ans);
return 0;
}

LOJ #2731 [JOI2016春季合宿]Solitaire (DP、组合计数)的更多相关文章

  1. LOJ #2733 [JOI2016春季合宿]Sandwiches (DP)

    题目链接 https://loj.ac/problem/2733 题解 神仙题-- 首先可以观察到一个结论: 目标块的两块小三明治一定分别是最后和倒数第二个被吃的. 由此我们可以考虑这两块谁先被吃.这 ...

  2. LOJ #2734 Luogu P3615 [JOI2016春季合宿]Toilets (结论、贪心)

    题目链接 (loj) https://loj.ac/problem/2734 (luogu) https://www.luogu.org/problem/P3615 题解 嗯,考场上肝了\(3h\)然 ...

  3. BZOJ 4221 [JOI2012春季合宿]Kangaroo (DP)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4221 题解 orz WYC 爆切神仙DP 首先将所有袋鼠按大小排序.考虑从前往后DP, ...

  4. 3.29省选模拟赛 除法与取模 dp+组合计数

    LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...

  5. JOI2017 春季合宿:Railway Trip

    自己的AC做法似乎离正解偏了十万八千里而且复杂了不少--不管怎样还是记录下来吧. 题意: 题目链接: JOISC2017 F - AtCoder JOISC2017 F - LOJ \(N\)个车站排 ...

  6. UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】

    题目分析: 好像跑得很快,似乎我是第一个启发式合并的. 把玩具看成区间.首先很显然如果有两个玩具的进出时间有$l1<l2<r1<r2$的关系,那么这两个玩具一定在不同的栈中间. 现在 ...

  7. [JOI2017春季合宿]Port Facility[set、二分图]

    题意 你有两个栈,有 \(n\) 个货物,每个货物有一个进栈时间和出栈时间(所有时间的并集是1~2n),问有多少种不同的入栈方案. \(n\le 10^6\) 分析 把每个货物的存在看成区间,相交的区 ...

  8. UOJ #356. 【JOI2017春季合宿】Port Facility

    Description 小M有两个本质不同的栈. 无聊的小M找来了n个玩具.之后小M把这n个玩具随机顺序加入某一个栈或把他们弹出. 现在小M告诉你每个玩具的入栈和出栈时间,现在她想考考小S,有多少种方 ...

  9. UOJ #357. 【JOI2017春季合宿】Sparklers

    Description 小S和小M去看花火大会. 一共有 n 个人按顺序排成一排,每个人手上有一个仅能被点燃一次的烟花.最开始时第 K 个人手上的烟花是点燃的. 烟花最多能燃烧 T 时间.每当两个人的 ...

随机推荐

  1. 终身机器学习(Lifelong Machine Learning)综述

    终身机器学习(Lifelong Machine Learning)综述 2015年10月23日 17:34:57 qrlhl 阅读数 7805更多 分类专栏: 机器学习   版权声明:本文为博主原创文 ...

  2. 【POI】使用POI 创建生成XLS,打开xls文件提示【此文件中某些文本格式可能已经更改,因为它已经超出最多允许的字体数。】

    使用POI 创建生成XLS,打开xls文件提示[此文件中某些文本格式可能已经更改,因为它已经超出最多允许的字体数.] 原因: 是因为在POI处理xls的过程中,太多次调用了: HSSFFont fon ...

  3. url请求

    --[[local g = require 'library.global'--__ml_ss = mlc.prefix.ml_psession..tostring(os.time());local ...

  4. TensorFlow良心入门教程

    All the matrials come from Machine Learning class in Polyu,HK and I reorganize them and add referenc ...

  5. java基础3(异常)

    1.异常的体系 1)请描述异常的继承体系 异常继承体系为:异常的根类是 java.lang.Throwable,其下有两个子类:java.lang.Error 与 java.util.Exceptio ...

  6. Spring自定义标签的实现

    首先 简单写下 spring xml解析的过程 通过一段简单的 调用spring代码开始 public static void main(String[] args) { ApplicationCon ...

  7. vue-cli3.x创建项目vue create hello-world

    在git中输入指令vue create hello-world,没反应,因为vue-cli的版本问题,必须3.x版本才能使用这个指令于是按照官网的提示升级vue vue-cli从2.x版本升级到3.x ...

  8. Ubuntu下编译boost for Android

    下载https://github.com/moritz-wundke/Boost-for-Android 解压后进入目录 运行 ./build-android.sh $(NDK_ROOT) NDK_R ...

  9. ASE19团队项目alpha阶段model组 scrum2 记录

    本次会议于11月4日,19时整在微软北京西二号楼sky garden召开,持续25分钟. 与会人员:Jiyan He, Kun Yan, Lei Chai, Linfeng Qi, Xueqing W ...

  10. Samba passwd smbpasswd and tdbsam

    ome commands to convert samba backend password-databases. If you use "passdb backend = smbpassw ...