1 条题解
-
0
自动搬运
来自洛谷,原作者为

max67
bobo搬运于
2025-08-24 22:26:02,当前版本为作者最后更新于2022-09-24 20:58:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前言
感谢
https://www.luogu.com.cn/user/233462#following指导(看分类过程的可以看有灰色竖线的部分)
题解
设与男孩相邻的数量为 ,与女孩相邻的数量为 。
首先可以凭感觉知道:这种既带构造又带环的题目,大多都要分类讨论。为了使我们讨论的顺畅一点,首先我们先特判一些特殊情况,创造出一些性质:
当 时,注意到此时不能填
B,必须全填G。容易算出此时的 的值为 。因此当且仅当 时有解。 的情况同理。那么此时满足答案里面至少有一个
G,至少有一个B。分别考虑每个字符的贡献,注意到这仅与他两边的字符有关。那么考虑把一段连续的字符缩成一个连续段,分别讨论每个连续段的贡献(假设这个连续段的字符都是
B):-
设这个连续段的长度为 ,首先可以观察出与这个连续段相邻的连续段的字符都是
G -
当 时,注意到他两边的字符都是
G,那么只有对 有 的贡献 -
当 时,连续段两端的字符与
G相邻,因此对 有 的贡献;连续段里的所有字符都与B相邻,对 有 的贡献。 -
注意连续段个数必须为偶数,若为奇数的话一定会有两个字符相同的连续段相邻,就会不合法。
由于上面的分类贡献比较复杂,因此考虑对于总数() 的贡献。当连续段的长度为 时,对 有 的贡献;当连续段的长度为 时,对 有 的贡献。
因此若有 个大于 的连续段, 的总数就为 。
因此 ,所以若 或 就无解。
现在,我们知道了 的表达式:。
然后似乎很难讨论,那么我们尝试挖掘 和 的性质。观察 的定义可得
-
因为总人数小于等于 ,因此 。
-
有 ,即 ,变形一下有: 。
-
同理,有
但这样还不够,一个常见的构造想法是先构造出一个基础解,再在上面进行增添。那么一个朴素的思路就是往联通块里面插数。那么手模一下,有:
- 当一个连续段的个数大于 时,假设字符为
B。往里面插一个相同的字符,只会使得 的值增加 。
那么我们可以首先创建 个长度为 的连续段。注意到上面的性质,也就是只要有一个连续段就能单独调整 或 ,那么我们肯定保证要给每个字符至少一个连续段。
注意到 ,即当 时是上面的想法可能的,那么我们先讨论这种情况。由于 ,一个暴力的想法是直接给 分 个上下浮动的连续段。
当 时,我们规定一个字符分到 个段(设是字符
B),另一个字符分到 (设是G)。因为 为奇数,还需要额外增加一个长度为 的连续段(否则有两个连续段会合并),字符为分到连续段数小的那个(假设为G)。那么我们现在对于 已经有 的贡献, 已经有 的贡献。由于 ,也就是说若满足 。因此我们的当前构造不会不合法的。由于我们能任意增加 或 的值(往任意一个长度大于等于 的连续段里面插数),因此构造是合法的。同理可以构造 。考虑 的情况怎么办。推一下式子,有:。由于 为奇数,设 ,那么 ,即 在模 意义下的模数为 。
那么考虑 的定义,因为 ,一个字符最多产生 的贡献,也就是说任意一个位置的相邻的两个字符都不同。假设答案中位置为 的字符为 。有 ,即 ,而 ,就导出了矛盾。
因此 的情况不合法。对于 的情况,同理讨论即可。
当 时,初始设置 个长度为 的连续段,其中 个连续段的颜色为
B, 个连续段的字符为G。那么对于 的贡献已经为其次我们往其中一个字符为
B的连续段放入 个字符,往其中一个字符为G的连续短放入 个字符。当 时,若 ,不合法,否则设 ,设置长度为 的连续段 个, 个连续段的字符为
B, 个连续段的字符为G。再增加一个长度为 的连续段,字符为G。然后分给其中一个字符为B的连续段 个字符,分给其中一个字符为G的连续短 个字符。然后分类讨论 的情况。
当 时,那么每个连续段的长度为 ,因此若 为奇数,则至少为出现一个长度为 的连续段,无解。那么 为偶数,分配了 个
B和G。易得 时合法,否则不合法。当 时,设一共有 个连续段。其中 个连续段的字符为
B,另外的为G。假设 ,那么抽出其中一个字符为B的连续段,加入一个字符。那么此时对 的贡献为 ,对 的贡献为 。由于 ,有 。因此合法。当 时同理。当 时,由于上面的构造是唯一解,所以不合法。(注意数据没有这个情况)
然后这题就做完了 QAQ。
代码
注意一下优先级:
1?putchar('B'),putchar('B'):putchar('G'),putchar('G')的输出为
BBG。#include<bits/stdc++.h> #define pc putchar using namespace std; const int N=1e5+1e3; int n,a,b; void print(){puts("Impossible");exit(0);} int main() { scanf("%d%d%d",&n,&a,&b); // a 个孩子站在一个男孩旁边 // b 个孩子站在一个女孩旁边 if(a+b<n||((a+b-n)&1))print(); if(a==0||b==0) { if(a+b!=n)print(); if(a==0)for(int i=1;i<=n;i++)pc('G'); if(b==0)for(int i=1;i<=n;i++)pc('B'); exit(0); } int t=a+b-n>>1; if(t==0) { if(n%2||a!=n/2||b!=n/2)print(); for(int i=1;i<=n;i++)pc(i&1?'G':'B'); exit(0); } if(t==1) { if(a==b)print(); if(a>b) { for(int i=1;i<=a-b+1;i++)pc('B'); for(int i=1;i<=n-(a-b+1);i++)pc(i&1?'G':'B'); } if(a<b) { for(int i=1;i<=b-a+1;i++)pc('G'); for(int i=1;i<=n-(b-a+1);i++)pc(i&1?'B':'G'); } exit(0); } if(t%2==0) { a-=2*t;b-=2*t; for(int i=1;i<=a+2;i++)pc('B'); for(int i=1;i<=b+2;i++)pc('G'); for(int i=1;i<=t-2;i++)pc(i&1?'B':'G'),pc(i&1?'B':'G'); exit(0); } a-=2*t;b-=2*t; if(!a&&!b)print(); if(a) { for(int i=1;i<=a+1;i++)pc('B'); for(int i=1;i<=b+2;i++)pc('G'); for(int i=1;i<=t-2;i++)pc(i&1?'B':'G'),pc(i&1?'B':'G'); pc('G'); exit(0); } if(b) { for(int i=1;i<=b+1;i++)pc('G'); for(int i=1;i<=a+2;i++)pc('B'); for(int i=1;i<=t-2;i++)pc(i&1?'G':'B'),pc(i&1?'G':'B'); pc('B'); exit(0); } return 0; }后记
在写题时,突然想起了 P6892 [ICPC2014 WF]Baggage。虽然说两个构造方法不同,但是分类讨论的痛苦是相同的。
-
- 1
信息
- ID
- 6192
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者