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. Ruby页面,循环赋值方法(类似java EL表达式赋值)

    ------------前台代码--------------- <% @form_hash.each_with_index do |f,index| %> <% item = f[: ...

  2. vs code配置git

    在项目目录执行 git init 修改.git文件夹下的config文件 [core] repositoryformatversion = 0 filemode = false bare = fals ...

  3. HDU - 6305 RMQ Similar Sequence(笛卡尔树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6305 题目 对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0 ...

  4. java实现Excel数据导出

    java实现Excel数据导出: 目前,比较常用的实现Java导入.导出Excel的技术有两种Jakarta POI和Java Excel Jakarta POI 是一套用于访问微软格式文档的Java ...

  5. 使用idea创建springboot项目并打成war包发布到tomcat8上

    1.将pom.xml中的打包方式修改为war <groupId>com.borya</groupId> <artifactId>Project</artifa ...

  6. 055、创建macvlan网络 (2019-03-22 周五)

    参考https://www.cnblogs.com/CloudMan6/p/7364332.html     创建macvlan网络,需要指定使用哪块物理网卡进行通信   -o parent=ens1 ...

  7. flask请求异步执行(转载)

    Flask默认是不支持非阻塞IO的,表现为: 当 请求1未完成之前,请求2是需要等待处理状态,效率非常低. 在flask中非阻塞实现可以由2种: 启用flask多线程机制 # Flask from f ...

  8. centos 6.8安装redis

    1. 下载到redis下载页面https://redis.io/download下载对应版本的reids安装包,如:redis-${version}.tar.gz . 2. 安装redis的详细安装步 ...

  9. MySQL 数据库应用程序编程

    普通用户使用客户端应用程序(Client Application)和服务器程序(Server Application)通信以取得服务, 而服务器程序通常要和数据库服务器通信以取得数据存取服务, 这时就 ...

  10. 4.mycat部署

    1.准备工作 mycat依赖Java环境,所以必须安装jdk yum install java-1.8.0-openjdk-devel.x86_64 配置JAVA_HOME环境变量 ls -lrt / ...