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. 【SQL】SQL中on条件与where条件的区别

     #前言 数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时 ...

  2. 网络编程基础【day09】:堡垒机前戏(十一)

    本节内容 1.堡垒机前戏 2.SSHClient 3.SFTPClient 一.堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 ...

  3. Win10升级.NET Framework 3.5或2.0遇到错误0x800f081f怎么办

    为了让win10系统更好地运行游戏,很多玩家都会在电脑中安装.NET Framework 3.5或.NET Framework 2.0.不过,部分用户在更新升级.NET Framework 3.5和2 ...

  4. 解决浏览器跨域限制方案之WebSocket

    WebSocket是在HTML5中引入的浏览器与服务端的通信协议,可以类比HTTP. 可以在支持HTML5的浏览器版本中使用WebSocket进行数据通信,常见的案例是使用WebSocket进行实时数 ...

  5. Android 全屏设置和禁止横屏竖屏切换

    android:screenOrientation="portrait" #禁止屏幕横竖切换,portrait为纵向,landscape为横向

  6. daemon_inetd函数

    #include <syslog.h> extern int daemon_proc; /* defined in error.c */ void daemon_inetd(const c ...

  7. asp.net上传图片,上传图片

    想必很多人工作中经常需要实现上传图片的功能. 先引用此插件 http://files.cnblogs.com/files/hmYao/jquery-form.js. 前台代码 <form dat ...

  8. 建立一个漂亮的PHP验证码类文件及调用方式

    //验证码类class ValidateCode { private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789';/ ...

  9. SQL手工注入入门级笔记(更新中)

    一.字符型注入 针对如下php代码进行注入: $sql="select user_name from users where name='$_GET['name']'"; 正常访问 ...

  10. Git学习之忽略特殊文件.gitignore的配置

    1.Mac中使用Git上传项目代码时忽略.DS_Store文件 简单的说Mac每个目录都会有个文件叫.DS_Store,它是用于存储当前文件夹的一些Meta信息.所以每次查看Git目录的状态,如果没有 ...