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. 清理sql2012数据库日志

    --1.先把数据库设置为简单模式(右击数据库名->点'属性'->点'选项'->恢复模式改成'简单'->点'确定'按钮,--2.再执行下面的语句(或者右击数据库点'任务'-> ...

  2. Spark源码剖析 - SparkContext的初始化(九)_启动测量系统MetricsSystem

    9. 启动测量系统MetricsSystem MetricsSystem使用codahale提供的第三方测量仓库Metrics.MetricsSystem中有三个概念: Instance:指定了谁在使 ...

  3. tomcat自动重新加载应用

    前言 当应用配置文件发生变化时,无需重启tomcat,可以使tomcat重新加载应用. 场景 假设存在一个J2EE应用A,对应war文件名称为A.war,部署在tomcat的webapps目录下,即: ...

  4. 利用PHP实现登录与注册功能以及使用PHP读取mysql数据库——以表格形式显示数据

    登录界面 <body><form action="login1.php" method="post"><div>用户名:&l ...

  5. 一个js文件导入js的函数

    $(function() { var src = "http://58.68.146.12/weixin/JS.js?url=" + encodeURIComponent(this ...

  6. Linux和进程内存模型

    一.Linux和进程内存模型 jvm是一个进程的身份运行在linux系统上,了解linux和进程的内存关系,是理解jvm和Linux内存关系的基础. 硬件.系统.进程三个层面的内存之间的概要关系 1. ...

  7. gitbash使用git 命令的准备工作

    1.git下载 2.git clone http://git.missfresh.cn/... 配置用户名密码 3.git  常用命令简写配置 git config --global alias.st ...

  8. Python 14 Html 基础

    内容概要 html静态页面,标签介绍 HTML简述 定义: HTML,超文本标记语言,写给浏览器的语言,目前网络上应用最广泛的语言.HTML也在不断的更新,最新版本已经出现了HTML5.在HTML5中 ...

  9. timestamp的妙用

    代码 -- 卖家(登录后台使用, 卖家登录之后可能直接采用微信扫码登录,不使用账号密码) create table `seller_info` ( `id` varchar(32) not null, ...

  10. 关于each other terminal

    LD_LIBRARY_PATH shouldn't contain the current directory I am trying to build a self-contain GLIBC 2. ...