归纳每一次操作后必然是两个颜色相同的连续段(即ww...bb...或bb...ww...),对操作的位置分类讨论不难证明正确性

当$c_{1}=c_{n}$,由于端点颜色不会修改,再根据该结论,可以得到$f(s,c_{i})=c_{1}\cdot n$(w为0,b为$n$)

当$c_{1}\ne c_{n}$(以下假设$c_{1}=b$且$c_{n}=w$),令$x=\min_{c_{i}=w}i$且$y=\max_{c_{i}=b}i$,考虑答案的上下限,最坏情况下即为$[1,x)$,最好情况下为$[1,y]$

对$x-1$和$y+1$哪个先取分类讨论:

1.若$x-1$先取,则当选择$y$后(也有可能是先选$y$再选$x-1$,但同理),$[1,y]$必然都为黑色(且不会再被翻转),即达到上限,因此如果$x-1$到$s$的距离小于等于$s$到$y+1$的距离,则答案为$[1,y]$

2.若$y+1$先取,类似的可以得到$[x,n]$都为白色,即答案取到下限$[1,x)$,因此如果$x-1$到$s$的距离大于$s$到$y+1$的距离,则答案为$[1,x)$

(另外对于$c_{1}=w$且$c_{n}=b$,不是两倍而是$s'=n-s+1$时的答案)

这显然包含了所有情况,即答案仅与$x$、$y$和$s$有关,得到了一个暴力$o(n^{3})$的做法,代码如下

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define mod 998244353
5 int n,mi[N],ans[N];
6 int main(){
7 scanf("%d",&n);
8 if (n==1){
9 printf("%d",(mod+1)/2);
10 return 0;
11 }
12 mi[0]=1;
13 for(int i=1;i<=n;i++)mi[i]=mi[i-1]*2%mod;
14 for(int i=2;i<=n;i++){
15 for(int j=1;j<=n;j++)ans[j]=(ans[j]+i-1)%mod;
16 for(int j=i+1;j<n;j++)
17 for(int k=1;k<=n;k++)
18 if (abs(i-1-k)<=abs(j+1-k))ans[k]=(ans[k]+1LL*j*mi[j-i-1])%mod;
19 else ans[k]=(ans[k]+1LL*(i-1)*mi[j-i-1])%mod;
20 }
21 int inv=1;
22 for(int i=1;i<=n;i++)inv=1LL*(mod+1)/2*inv%mod;
23 for(int i=1;i<=n;i++)printf("%lld\n",(ans[i]+ans[n-i+1]+1LL*mi[n-2]*n)%mod*inv%mod);
24 }

将$y=x-1$的特殊情况累加后即为$\frac{n(n-1)}{2}$,然后对于$k$的枚举改为差分,时间复杂度降为$o(n^{2})$,代码如下

 1     for(int i=2;i<=n;i++)
2 for(int j=i+1;j<n;j++){
3 int k=(j+i)/2;
4 ans[1]=(ans[1]+1LL*j*mi[j-i-1])%mod;
5 ans[k+1]=(ans[k+1]-1LL*(j-i+1)*mi[j-i-1]%mod+mod)%mod;
6 }
7 for(int i=2;i<=n;i++)ans[i]=(ans[i]+ans[i-1])%mod;
8 int inv=1,s=1LL*n*(n-1)/2%mod;
9 for(int i=1;i<=n;i++){
10 inv=1LL*(mod+1)/2*inv%mod;
11 ans[i]=(ans[i]+s)%mod;
12 }

进一步的,对于$ans[1]$的修改比较好处理,对于$ans[k+1]$的修改可以枚举$j-i$,那么$k=\frac{j-i}{2}+i$,再进行一次差分即可,时间复杂度即降为$o(n)$

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define mod 998244353
5 int n,mi[N],ans[N];
6 int main(){
7 scanf("%d",&n);
8 if (n==1){
9 printf("%d",(mod+1)/2);
10 return 0;
11 }
12 mi[0]=1;
13 for(int i=1;i<=n;i++)mi[i]=mi[i-1]*2%mod;
14 for(int i=1;i<=n-3;i++){
15 ans[i/2+3]=(ans[i/2+3]-1LL*(i+1)*mi[i-1]%mod+mod)%mod;
16 ans[i/2+n-i+1]=(ans[i/2+n-i+1]+1LL*(i+1)*mi[i-1]%mod)%mod;
17 }
18 for(int i=2;i<=n;i++)ans[i]=(ans[i]+ans[i-1])%mod;
19 for(int i=3;i<n;i++)ans[1]=(ans[1]+1LL*i*(mi[i-2]-1))%mod;
20 for(int i=2;i<=n;i++)ans[i]=(ans[i]+ans[i-1])%mod;
21 int inv=1,s=1LL*n*(n-1)/2%mod;
22 for(int i=1;i<=n;i++){
23 inv=1LL*(mod+1)/2*inv%mod;
24 ans[i]=(ans[i]+s)%mod;
25 }
26 for(int i=1;i<=n;i++)printf("%lld\n",(ans[i]+ans[n-i+1]+1LL*mi[n-2]*n)%mod*inv%mod);
27 }

[atARC109E]1D Reversi Builder的更多相关文章

  1. I - 一次元リバーシ / 1D Reversi(水题)

    Problem Statement Two foxes Jiro and Saburo are playing a game called 1D Reversi. This game is playe ...

  2. 2018.09.20 atcoder 1D Reversi(模拟)

    传送门 考虑每次摆石头都会消去最外层的一个连续颜色串. 所以只用统计一下有多少段颜色即可. 代码: #include<bits/stdc++.h> using namespace std; ...

  3. ARC109F - 1D Kingdom Builder

    一行格子,其中小于\(0\)的格子为白色,大于\(n\)的格子为黑色,中间的格子颜色由题目给出. 有一些格子需要被标记.标记按照以下规则进行:选择一个颜色\(c\),找到一个未标记的 旁边有标记点的 ...

  4. [atARC109F]1D Kingdom Builder

    考虑最终有石子的位置的状态,判断一种状态是否可行 反过来,依次删除石子,删除条件是:当删除的石子是该段最后一个(即其两边都没有石子了),要求除其以外,每个连续段旁边的两个点都与其颜色不同 构造一种删除 ...

  5. AtCoder Regular Contest 109

    Contest Link 为什么还没有 Official Editorial 啊--哦,原来是日文题解,那没事了. A - Hands 有两幢 100 层的楼房 \(A,B\) ,将地面所在的楼层称为 ...

  6. atcoder题目合集(持续更新中)

    Choosing Points 数学 Integers on a Tree 构造 Leftmost Ball 计数dp+组合数学 Painting Graphs with AtCoDeer tarja ...

  7. 【AtCoder】ARC063

    ARC063 C - 一次元リバーシ / 1D Reversi 不同的颜色段数-1 #include <bits/stdc++.h> #define fi first #define se ...

  8. 23种设计模式--建造者模式-Builder Pattern

    一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建 ...

  9. PHP设计模式(五)建造者模式(Builder For PHP)

    建造者模式:将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示的设计模式. 设计场景: 有一个用户的UserInfo类,创建这个类,需要创建用户的姓名,年龄,爱好等信息,才能获得用 ...

随机推荐

  1. Kubernetes Job Controller 原理和源码分析(一)

    概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...

  2. 用C++实现的数独解题程序 SudokuSolver 2.4 及实例分析

    SudokuSolver 2.4 程序实现 本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析 里发现的第三个不完全收缩 grp 算法 thirdGreenWor ...

  3. java---String 和 StringBuffer

    Java-String和StringBuffer类 Java String 类 字符串在Java中属于对象,Java提供String类来创建和操作字符串. 创建字符串 创建字符串常用的方法如下: ​ ...

  4. SharkCTF2021 Classic_Crypto_king2

    crypto类题. 题面如下: 前面的代码给出了原理:后面的字符串第一行是print出的key,第二行是密文. 加密原理是,首先对table进行乱序处理,然后将明文flag按照(顺序table--&g ...

  5. Sequence Model-week3编程题2-Trigger Word Detection

    1. Trigger Word Detection 我们的触发词将是 "Activate.".每当它听到你说 "Activate.",它就会发出 "c ...

  6. NOIP模拟83(多校16)

    前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...

  7. UltraSoft - Alpha - Scrum Meeting 5

    Date: Apr q9th, 2020. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM 统筹个人进度,协助推进进度 辅助前后端连接工作 刘zh 前端 完 ...

  8. 搬运1:关于对C语言中数组名取地址加减等操作的一点探究

    对于数组名取地址强制转换的操作 偶然在晚上学了C语言指针后网页闲逛找题时,被一个数组名取地址搞糊涂了,在自己试验加探索后我稍微悟了一点东西. 代码如下: #include<stdio.h> ...

  9. 2021.9.14考试总结[NOIP模拟53]

    T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...

  10. 深入理解和运用Pandas的GroupBy机制——理解篇

    GroupBy是Pandas提供的强大的数据聚合处理机制,可以对大量级的多维数据进行透视,同时GroupBy还提供强大的apply函数,使得在多维数据中应用复杂函数得到复杂结果成为可能(这也是个人认为 ...