Problem

CODE-FESTIVAL 2017 qual A

洛谷账户的提交通道

题意:有一个\(n\)行\(m\)列的方格,在边界外有可能有机器人(坐标为\((0,x),(n+1,x),(x,0),(x,m+1)\),机器人方向朝内(也就是左边界外的机器人朝右,上边界外的机器人朝内……),机器人有自己独特的颜色(没有两个机器人颜色相同)。

给机器人安排一个出发顺序,机器人将依次出发,对于每个机器人,走过的路上会留下自己的颜色,它将继续前进除非出了另一方的边界或遇到了其他机器人留下的颜色。求有多少种最终状态(即方格染色情况不同)

\(n,m\leq 10^5\)

输入是给出每个边界外是否有机器人,即机器人数量不超过\(2(n+m)\leq 4\times 10^5\)

Solution

想了半天未果,然后看到题解的图恍然大悟

情况太复杂,考虑简化版的情况:先考虑只有一个角或半平面的情况


若棋盘只有一个角(角块)

可假定机器人仅从上、左出发,设有\(n\)行\(m\)列,共\(n+m\)个机器人

先画出一个\(n\)行\(m\)列的方格,共有\(nm\)个交点,随意画出一种结果,发现如果始终沿着最内侧线走,并在最下边和最右边加限制边,可以得到下面这张图(图中红色路径):

此时发现其中的红色路径依次穿过了\(n+m\)条直线(尽管有的没和线段相交,但和延长线相交),而实际上整张图最终的状态也只会和这个穿过的顺序有关

由于穿过\(n\)条横线的顺序是固定的,穿过\(m\)条横线的顺序也是固定的,所以这个状态数相当于找\(n\)个黑球和\(m\)个白球排成一列的不同方案数,由组合知识可知方案数为\(\binom {n+m}n\)


若棋盘只有一个半平面

可假定机器人从上、左、右出发

利用上面的思想:若第一个机器人是上下移动的,则会将这个状态化为一个子问题;若第一个机器人是从左往右的,则会将这个状态划分为两个角的情况(也就是上面说的)

这样就能简单地推广到全平面问题了:第一个机器人将局面划分为两个半平面

然后经过思考得知,这样复杂度为\(O(nm)\),虽然通过不了此题,但若是在\(OI\)赛制的考试中,就能与别人拉开巨大的差距


对称思想

上面的做法是通过不了此题的,思考半天也没发现可以利用组合数公式优化 然后就翻开了罪恶的题解……

先放一张题解的图

之前在四分之一角那一块中提到的红线,在官方题解里它是一个红色区域

  • 在角中红色区域是一个单调的阶梯状是因为只有上面和左边的机器人
  • 考虑到在半平面情况中,还存在下边的机器人,所以红色区域为一个单峰的阶梯状

如果利用之前角块的思想解半平面,可以利用图中所给的对称轴,将单峰的阶梯对称为单调的阶梯……然后就能用角块的公式来解半平面了!

列下公式:若左边有\(n\)个机器人,上面和下面共有\(m\)个机器人,则答案为\(\binom {n+m}n-\binom {n+m-1}n=\binom {n+m-1}{n-1}\)(之所以要减去是因为至少要沿着对称轴走一次才能保证对称的正确性)


汇总

然后就可以枚举第一只机器人如何划开平面将其划分为半平面的,假设第一只机器人是走竖直线段

相应的,由于不好处理半平面中“一只机器人走完仍然是一个半平面”的问题,所以可以枚举不会出现这种状态的左右边界,然后这个枚举可以用前缀和优化成\(O(n)\)


特判

  • 注意第一只机器人的走向可能是横向,也可能是纵向
  • 注意组合数部分不要爆负
  • 注意若同一列(行)若有上下两个机器人,且这两个机器人之间没有障碍,需要将答案乘以2(因为可以上面先走或下面先走)
  • 若根本没有机器人,应该输出1

Code

再不懂就看代码吧

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int N=101009,p=998244353,inv2=p+1>>1;
char A[N],B[N],C[N],D[N];
int fac[N<<2],inv[N<<2];
int n,m,ans; inline int qpow(int A,int B){
int res(1);while(B){
if(B&1)res=(ll)res*A%p;
A=(ll)A*A%p,B>>=1;
}return res;
} inline int Com(int nn,int mm){return (ll)fac[nn]*inv[mm]%p*inv[nn-mm]%p;}
void prework(int A){
fac[0]=inv[0]=1;
for(int i=1;i<=A;++i)fac[i]=(ll)fac[i-1]*i%p;
inv[A]=qpow(fac[A],p-2);
for(int i=A-1;i;--i)inv[i]=(ll)inv[i+1]*(i+1)%p;
} void work(){
int left=0,right=0,l=0,r=0,pre=1,val;
for(int i=1;i<=n;++i)left+=A[i]-'0',right+=B[i]-'0';
for(int i=m;i;--i)r+=C[i]-'0'+D[i]-'0';
for(int i=1;i<=m;i++){
l+=C[i]-'0'+D[i]-'0';
r-=C[i]-'0'+D[i]-'0';
if(C[i]=='0' and D[i]=='0')continue;
if(C[i]=='1' and D[i]=='1')pre=2ll*pre%p;
if(right)val=Com(right+r-1,r);
else val=(!r); ans=(ans+(ll)pre*val)%p;
if(left)val=Com(left+l-1,l);
else val=(!l); pre=(pre+val)%p;
}
} int main(){
scanf("%d%d",&n,&m);
prework(n+m+n+m);
scanf("%s%s",A+1,B+1);
scanf("%s%s",C+1,D+1);
bool died=true;
for(int i=1;i<=n;++i)
if(A[i]=='1' or B[i]=='1' or C[i]=='1' or D[i]=='1')
{died=false;break;}
if(died){puts("1");return 0;}
work();
swap(n,m);swap(A,C);
swap(B,D);swap(C,D);
work();
printf("%d\n",ans);
return 0;
}

题解-AtCoder Code-Festival2017qualA-E Modern Painting的更多相关文章

  1. [AtCoder Code Festival 2017 QualB D/At3575] 101 to 010 - dp

    [Atcoder Code Festival 2017 QualB/At3575] 101 to 010 有一个01序列,每次可以选出一个101,使其变成010,问最优策略下能操作几次? 考虑像 11 ...

  2. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

  3. 题解【AtCoder - CODE FESTIVAL 2017 qual B - D - 101 to 010】

    题目:https://atcoder.jp/contests/code-festival-2017-qualb/tasks/code_festival_2017_qualb_d 题意:给一个 01 串 ...

  4. 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数

    蒟蒻__stdcall终于更新博客辣~ 一下午+一晚上=一道计数题QAQ 为什么计数题都这么玄学啊QAQ Prelude 题目链接:这里是传送门= ̄ω ̄= 下面我将分几个步骤讲一下这个题的做法,大家不 ...

  5. Atcoder Code Festival 2017 qual C 10.22 D题题解

    [题意概述] 给出一个只有小写字母的序列,问最少把序列分成几段可以满足每一段可以通过变换成为回文串.变换指的是交换子序列中的字母的位置. [题解] 我们把a~z分别设为2^0~2^25,每个子序列满足 ...

  6. Atcoder CODE FESTIVAL 2017 qual B D - 101 to 010 dp

    题目链接 题意 对于一个\(01\)串,如果其中存在子串\(101\),则可以将它变成\(010\). 问最多能进行多少次这样的操作. 思路 官方题解 转化 倒过来考虑. 考虑,最终得到的串中的\(' ...

  7. 题解-AtCoder Code-Festival2017 Final-J Tree MST

    Problem \(\mathrm{Code~Festival~2017~Final~J}\) 题意概要:一棵 \(n\) 个节点有点权边权的树.构建一张完全图,对于任意一对点 \((x,y)\),连 ...

  8. AtCoder Code Festival 2017 Team Relay J - Indifferent

    题目大意:共$2n$个价格$p_i$.两人轮流取.你每次取最大的,对方每次随机取.问你取的期望和是多少. 题解:从小到大排序,$\sum\limits_{i=0}^{2n-1} \frac{i*p_i ...

  9. Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分

    题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...

随机推荐

  1. vue基础篇---路由的实现《2》

    现在我们来实现这样一个功能: 一个页面,包含登录和注册,点击不同按钮,实现登录和注册页切换: 编写父组件 index.html <div id="app"> <s ...

  2. IE6浏览器的bug问题及相关解决的方法

    IE6浏览器的bug问题及相关解决的方法 1.css浮动边距加倍错误(双倍边距BUG)的解决办法   该错误只影响ie而不影响其他浏览器,我们可以考虑用hack来解决!!!   解决方法:_displ ...

  3. Java高并发秒杀API之web层

    第1章 设计Restful接口 1.1前端交互流程设计 1.2 学习Restful接口设计 什么是Restful?它就是一种优雅的URI表述方式,用来设计我们资源的访问URL.通过这个URL的设计,我 ...

  4. Golang入门教程(三)beego 框架安装

    beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API.Web 及后端服务等各种应用,是一个 RESTful 的框架,主要设计灵感来源于 tornado.sinatra ...

  5. 【剑指offer】Java版代码(完整版)

    原文地址:https://blog.csdn.net/baiye_xing/article/details/78428561 一.引言 <剑指offer>可谓是程序猿面试的神书了,在面试中 ...

  6. vim学习之改头换面(基础配置)

    还记得在线有个维护博客园的学长说过,这网站的前端做的贼丑,今日一看果真如此.其实我想说毕竟干货多,没有那么多花花肠子.下面开始进入正题. 在入坑了sublime.vscode.atom.notepad ...

  7. 20秒教你如何写maven2的pom文件的依赖包

    所有Maven 库 需要的包 及 pom.xml 中 groupId  artifactId version 都可在这个网上收到. 例如:需要 通过 maven 在项目 中 添加 geronimo-k ...

  8. 【bzoj 4756】[Usaco2017 Jan] Promotion Counting

    Description The cows have once again tried to form a startup company, failing to remember from past ...

  9. sql插入oracle链接的数据

    报错OLE DB 访问接口 "OraOLEDB.Oracle" 返回了消息 "ORA-29275: 部分多字节字符". select addr from tes ...

  10. Coursera, Big Data 1, Introduction (week 1/2)

    Status: week 2 done. Week 1, 主要讲了大数据的的来源 - 机器产生的数据,人产生的数据(比如社交软件上的update, 一般是unstructed data), 组织产生的 ...