0%

题目大意

1. 题目定义

给定一个长度为 nn 的字符串 ss(由 01? 组成)和一个正整数 cc

函数 f(w)f(w) 的定义:

对于一个仅含 01 的字符串 ww,其值 f(w)f(w) 表示满足以下条件的 [0,1,,n1][0, 1, \dots, n-1] 全排列 pp 的总数:

  • 对于 1in1 \le i \le n,如果 wi=1w_i = 1,则排列 pp 中必须存在至少一个连续子段,其 MEX 值为 ii

  • 对于 1in1 \le i \le n,如果 wi=0w_i = 0,则排列 pp 中不得存在任何连续子段的 MEX 值为 ii

注:MEX(Minimum Excluded)指集合中未出现的最小非负整数。

2. 目标任务

通过将 ss 中的所有 ? 替换为 01 来构造字符串 ww。在所有满足 f(w)f(w) 不能被 cc 整除 的字符串 ww 中,计算 f(w)f(w) 的最小值

3. 输出要求

  • 输出该最小值对 109+710^9 + 7 取模的结果

  • 若不存在满足条件的 ww,则输出 1-1


4. 样例解释辅助理解

  • 样例 3 (n=4,c=100,s=1001n=4, c=100, s=1001)
    字符串固定为 10011001。此时 f(1001)=4f(1001) = 4,满足条件的排列包括 [0,2,3,1],[0,3,2,1],[1,2,3,0],[1,3,2,0][0,2,3,1], [0,3,2,1], [1,2,3,0], [1,3,2,0]。由于 44 不能被 100100 整除,答案为 44

  • 样例 7 (n=5,c=8,s=100?1n=5, c=8, s=100?1)
    若将 ? 替换为 0 得到 w=10001w=10001,经计算 f(w)=12f(w) = 12。由于 1212 不能被 88 整除,且经比较这是所有可能替换中的最小值,故输出 1212

  • 样例 2 (n=3,c=1,s=???n=3, c=1, s=???)
    无论如何替换 ?,任何整数 f(w)f(w) 都能被 11 整除。因此不存在满足 “不能被 cc 整除” 条件的 ww,输出 1-1

CF-1075-D1. Little String (Easy Version)(把序列生成的过程看成不断插入数字的过程)(插入过程可以写为一个循环,应该多少范围就多少范围,特判写在循环里面)

Untitled

思路讲解

那么是这样子的,这道题目如果把这个序列生成的这个过程看成从 0n10\sim n-1 不断插入的过程,那么如果 wi=0w_i=0,那么 ii 就插入在原来 0i10\sim i-1 之间的空当中。wi=1w_i=1,只能插入在 0i10\sim i-1 的两段。

D1 当中,我们采用如上方法得到答案。

这道题目,其实想让我们求的是在不被 cc 整除的前提下,能够得到的最小值。

那其实说白了,想让值比较小,那就除了首位,结尾,全部填 1 就完了(遇到 ?),不过现在就是这个不能被 cc 整除比较烦。

当然,除了首位,当 i1i-1 为偶数的时候,也应该填写这个 ‘1’,因为反正都要引入 22,那不如就引入一个 22

不过这道题目,其实就是一个分类讨论

对于非 2 的幂次,不额外引入任何奇数素因子,总是最好的。因此,采用这个我们之前说的策略:

那就除了首位,结尾,全部填 1 就完了(遇到 ?时)

那么对于 2 的幂次,先不断填 2 进去,发现不行了,我们就回退,乘以 i1i-1,注意逆序遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 对于 2 的幂次来说,能不引入 2 自然最好
for (int i=N-1;i>=1;--i) {
if (W[i]=='?') {
ll ans_c_backup=ans_c,ans_backup=ans;
ans_c*=2;
ans_c%=C;
ans*=2;
ans%=mod;
if (ans_c==0) { // 发现不对,回退乘以 2,乘以 i-1
ans_c=ans_c_backup;
ans=ans_backup;
ans*=(i-1);
ans%=mod;
ans_c*=i-1;
ans_c%=C;
}
}
}

不过是对于什么进行分类讨论呢?

我们上面有一些地方,加上原本的串,都已经确定了一些,把这一部分的值计算出来,我们记作 ansans。那么我们知道,ansansCC 的因子的交集就是 gcd(ans,C)\gcd(ans,C)(可以用该式子计算: gcd(ans,C)=gcd(ansmodC,C)\gcd(ans,C)= \gcd(ans\mod C,C))。那么 CC 当中还没有被消掉的因子的集合就是:

Cgcd(ans,C)\frac{C}{\gcd(ans,C)}

我们就是对还未被消掉的因子集合进行分类讨论

AC代码

AC

https://codeforces.com/contest/2189/submission/360006878

心路历程(WA,TLE,MLE……)

题目大意

题目总结:Little String (Easy Version)


核心定义

对于一个长度为 nn 的 01 字符串 ww 和集合 {0,1,,n1}\{0, 1, \dots, n-1\} 的全排列 pp,定义 f(w)f(w) 为满足以下所有条件的排列 pp 的总数:

  • wi=1w_i = 1 排列 pp 中必须存在至少一个连续子段 [pl,,pr][p_l, \dots, p_r],使得该子段的 MEX 等于 ii

  • wi=0w_i = 0 排列 pp 中不存在任何连续子段的 MEX 等于 ii

  • MEX 定义: 集合中未出现的最小非负整数。例如 mex([0,1,3])=2\text{mex}([0, 1, 3]) = 2mex([1,2])=0\text{mex}([1, 2]) = 0


任务要求

  • 输入: 长度为 nn 的字符串 ss(在本简单版本中不含问号,即 w=sw = s)和一个正整数 cc

  • 目标: 计算 f(s)f(s)

    • 如果 f(s)f(s) 不能被 cc 整除,输出 f(s)(mod109+7)f(s) \pmod{10^9 + 7}
    • 如果 f(s)f(s) 能被 cc 整除,或者不存在满足条件的字符串(针对含问号版本),则输出 1-1

样例解释对照

样例输入 n s c f(s) 计算与结果 解释
样例 3 4 1001 100 输出:4 满足条件的排列有 [0,2,3,1],[0,3,2,1],[1,2,3,0],[1,3,2,0][0,2,3,1], [0,3,2,1], \\ [1,2,3,0], [1,3,2,0]f(s)=4f(s)=4 不被 100 整除。
样例 6 5 10001 8 输出:12 f(s)=12f(s)=12。其中一个合法排列为 [0,4,3,2,1][0,4,3,2,1]1212 不被 8 整除。
样例 9 3 101 4 输出:2 合法排列为 [0,2,1],[1,2,0][0,2,1], [1,2,0]f(s)=2f(s)=2 不被 4 整除。
样例 2 3 111 1 输出:-1 无论 f(s)f(s) 为多少,任何整数都能被 c=1c=1 整除,故输出 1-1

思路讲解

image

题目中的条件,具体来说就是如上图所示,wi=0w_i=0,就是 ii0i10~i-1 分隔开,wi=1w_i=1,就是 ii 位于 0i10~i-1 的左边或者右边。

那么是这样子的,这道题目如果把这个序列生成的这个过程看成从 0n10~n-1 不断插入的过程,那么如果 wi=0w_i=0,那么 ii 就插入在原来 0i10~i-1 之间的空当中。wi=1w_i=1,只能插入在 0i10~i-1 的两段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for (int i=1;i<=N-1;++i) {
// 尝试往这个序列中插入 i
if (W[i]=='1') { // 插入在两端
ans*=2;
ans%=mod;
ans_c*=2;
ans_c%=C;
}else { // 插入在空当中
// 要破坏这个计划
ans*=(i-1);
ans%=mod;
ans_c*=i-1;
ans_c%=C;
}
}

然后这道题目就解决了。

AC代码

AC

https://codeforces.com/contest/2189/submission/359662289

心路历程(WA,TLE,MLE……)

题目大意:B. The Curse of the Frog

一只青蛙位于数轴的 00 点,目标是到达坐标 xx。青蛙掌握 nn 种跳跃技能,每种技能 ii 包含三个参数:

  • aia_i:最大跳跃距离。单次跳跃可从 kk 移动到 [k,k+ai][k, k + a_i] 范围内的任意整数点。

  • bib_i:回滚周期。每当 bi,2bi,3bib_i, 2b_i, 3b_i \dots 次使用该技能时,会触发诅咒。

  • cic_i:回滚距离。触发诅咒时,青蛙会先从当前位置 kk 后退到 kcik - c_i,然后再进行跳跃,最终落点范围为 [kci,kci+ai][k - c_i, k - c_i + a_i]

目标: 计算到达 xx 点所需经历的最小回滚总次数。如果无法到达,则输出 1-1


样例解释

样例 1

  • 输入: x=1x=1, 技能:a=3,b=3,c=3a=3, b=3, c=3

  • 过程: 第一次使用技能,不触发回滚(因为 1<b=31 < b=3)。直接从 00 跳到 11

  • 结果: 00 次回滚。

样例 4

  • 输入: x=8x=8, 拥有 55 种技能。其中包含 (12,1,11)(12, 1, 11)(10,1,4)(10, 1, 4) 等。

  • 过程:

    1. 使用第 11 种技能(b=1b=1):触发回滚,从 00 退到 11-11,跳到 11
    2. 使用第 44 种技能(b=2b=2):这是该技能第 11 次使用,不回滚,从 11 跳到 22
    3. 使用第 22 种技能(b=1b=1):触发回滚,从 22 退到 2-2,跳到 88
  • 结果: 总计 22 次回滚。

样例 6

  • 输入: x=10x=10, 技能:a=2,b=2,c=1a=2, b=2, c=1

  • 过程:

    • 11 次跳:不回滚,020 \to 2
    • 22 次跳:回滚(第 b=2b=2 次),2132 \to 1 \to 3
    • 33 次跳:不回滚,353 \to 5
    • 44 次跳:回滚(第 2b=42b=4 次),5465 \to 4 \to 6
    • 以此类推,通过交替回滚逐步前进。
  • 结果: 总计 33 次回滚。

思路讲解

starsilk 的代码。不需要的值,我们其实可以减掉。会清爽一些。

然后最后的这个向上取整除法,可以这样子想,没消耗一个回滚,可以前行多少距离?wa×bcw\gets a\times b-c。这个可以这么看,你先回滚 c-c(因为前面的免费步已经用完了),然后可以走 bb 步,每步 aa 的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false),cin.tie(0);
int T;
long long n,x,i,a,b,c,w;
for(cin>>T;T>0;T--)
{
cin>>n>>x;
w=0;
for(i=0;i<n;i++)
{
cin>>a>>b>>c;
x-=(b-1)*a;
w=max(w,a*b-c);
}
if(x<=0)cout<<"0\n";
else if(w==0)cout<<"-1\n";
else cout<<(x+w-1)/w<<'\n';
}
return 0;
}

AC代码

AC

https://codeforces.com/contest/2189/submission/359582687

心路历程(WA,TLE,MLE……)

题目大意

题目总结

问题描述

给定一个正整数 nn3n21053 \le n \le 2 \cdot 10^5)。你需要构造一个长度为 nn排列 pp(包含 11nn 的所有整数各一次),使得对于每一个 ii1in11 \le i \le n-1),都能在索引范围 [i,n][i, n] 中找到一个下标 jj(即 ijni \le j \le n),满足以下异或条件:

pi=pjip_i = p_j \oplus i

如果不存在满足条件的排列,则输出 1-1

输入输出

  • 输入:测试用例数量 tt,每个案例包含一个整数 nn

  • 输出:若存在,输出 nn 个整数表示排列 pp;否则输出 1-1


样例解释

n=3n=3 为例,输出为 2 1 3

  • i=1i=1 时:需要存在 j{1,2,3}j \in \{1, 2, 3\} 使得 p1=pj1p_1 = p_j \oplus 1
    已知 p1=2p_1=2,若取 j=3j=3,则 p31=31=2p_3 \oplus 1 = 3 \oplus 1 = 2。满足条件。

  • i=2i=2 时:需要存在 j{2,3}j \in \{2, 3\} 使得 p2=pj2p_2 = p_j \oplus 2
    已知 p2=1p_2=1,若取 j=3j=3,则 p32=32=1p_3 \oplus 2 = 3 \oplus 2 = 1。满足条件。

  • 所有 i[1,2]i \in [1, 2] 均满足条件,故 2 1 3 是合法解。

n=4n=4 为例:

  • 不存在任何长度为 44 的排列能满足上述所有约束,故输出 1-1

思路讲解

这道题目,一种方法是打表找规律,比较神秘,呃,也比较费时间,只不过由于我 C1 是打表打出来的,C2 也这样子尝试了,由于选取的规律比较奇怪,在某些情况下会出现问题,后需要与下标 lowbit(n)\text{lowbit}(n) 交换啊什么的,在这里就不介绍了。

不过可以总结一下,就是这种打表找规律的话,首先要确定没有答案的条件,其次就是写的检查器尽量报出更多的信息(在错误时),比如说这道题目,如果你构造出来的序列是错的,你写的检查器最好要报出来哪一位错了,有哪些位构造错误?这一位你填了什么值?反正信息越多越好。

那么构造方法如何解决 C1 呢?那么由于是要求 pi=pjip_i = p_j \oplus i,不妨就令 pi=i1p_i=i\oplus 1,把 1 放在最后就可以了,最后这样子生成的序列第一位可能有点问题,这个特判一下就行。

那么如果你会解决 C1 的话,其实只需要增加一行代码:

1
2
3
4
5
6
if (N%2==0) {
ans_ls[1]=N;
swap(ans_ls[1],ans_ls[lowbit(N)]);
}else {
ans_ls[1]=N-1;
}

swap(ans_ls[1],ans_ls[lowbit(N)]); 这一行代码。首先 lowbit(n)1\text{lowbit}(n)\oplus 1 肯定不愁找不到满足的 jj,因为他都处于第一个位置了。那么对于 nn 呢?那么由于 nnlowbit(n)lowbit(n)+2n≥n\oplus \text{lowbit}(n)≥\text{lowbit}(n)+2nn 是偶数),所以说也不用愁找不到 jj

当然,注意,nn 是 2 的幂次的时候是没有答案的,这也很容易理解,因为这个时候 nn 无论异或上 [1,n][1,n] 中的任何一个数字,其结果都超过了 [1,n][1,n] 的范围。

AC代码

AC
https://codeforces.com/contest/2189/submission/359568527

AC
https://codeforces.com/contest/2189/submission/359512601

心路历程(WA,TLE,MLE……)

题目大意

题目总结:F. Prufer Vertex

1. Prufer 顶点 P(T)P(T) 的定义

对于一棵拥有 n2n \ge 2 个节点的树 TT,按照以下标准过程生成 Prufer 序列:

  • 重复寻找当前树中编号最小的叶子节点并将其删除。

  • 直到树中只剩下最后 2 个节点。
    已知节点 nn 必然是最后剩下的两个节点之一,设另一个剩下的节点为 vv,则定义该树的 Prufer 顶点 P(T)=vP(T) = v

2. 问题描述

给定一个含有 nn 个顶点和 mm 条边的森林。假设该森林有 kk 个连通块,其大小分别为 s1,s2,,sks_1, s_2, \dots, s_k

已知将该森林添加 k1k-1 条边使其成为一棵树的方案总数为:

nk2i=1ksin^{k-2} \prod_{i=1}^{k} s_i

任务: 对于每一个 vv (1v<n1 \le v < n),计算在所有可能的加边成树方案中,满足 P(T)=vP(T) = v 的方案数量。

3. 输出要求

输出 n1n-1 个整数,第 ii 个整数表示满足 P(T)=iP(T) = i 的方案数,结果对 998244353998244353 取模。


样例解释(以样例 1 为例):

输入 n=3,m=0n=3, m=0,森林由三个孤立点 {1,2,3}\{1, 2, 3\} 组成。补全为树的方案共有 332(111)=33^{3-2} \cdot (1 \cdot 1 \cdot 1) = 3 种:

  1. 添加边 (1,2) 和 (1,3): 叶子节点为 2 和 3。最小叶子 2 被删除,剩余 {1,3}\{1, 3\}。故 P(T)=1P(T)=1

  2. 添加边 (2,1) 和 (2,3): 叶子节点为 1 和 3。最小叶子 1 被删除,剩余 {2,3}\{2, 3\}。故 P(T)=2P(T)=2

  3. 添加边 (3,1) 和 (3,2): 叶子节点为 1 和 2。最小叶子 1 被删除,此时 2 变为叶子,删除 2,剩余 {3}\{3\} 与另一节点(在此情况下 Prufer 过程最后剩下的非 nn 节点为 2)。

最终输出:1 2(代表 P(T)=1P(T)=1 有 1 种,P(T)=2P(T)=2 有 2 种)。

思路讲解

我们阐述一下题意,叶子在无根树树中应该就是指的是度为 1 的点(虽然给的是森林,不过我们最后都会连成树),样例 1 的答案生成过程如图所示:

image

我们发现,只要一个点,是只和最大点相连的点(最大点和该点连接且仅和该点连接),那么这个点一定可以被保下来。因为这个点,是最后成为这个叶子节点的。原因:反证法,如果比较早把这个点删除了,那么最大点就变为孤零零一个人了,这显然是不可能的。

那么更进一步的推论就是,答案一定是和最大点直接相连的点。不过,虽然我们知道了答案是和最大点直接相连的点,但是我们不太清楚,到底是哪个点。

我们进行一个猜测,就是以这个点为根的子树,其内部的最大点,是所有的子树中最大的(即其他子树中的最大点,都比这颗子树小)。这样子,在删除这个内部最大点之前,我们会把其他子树全部删除,最后就只剩一颗子树了,结果就确定了。

当然,这个所谓的内部最大点,就是次大值 n1n-1 啦, nn 为根,n1n-1 所在的子树的根就是所能留下来的点

不过现在的难点就来到了这个统计答案。

n1n-1 的特殊情况看起,我们发现,如果 n1n-1 已经连接在了 nn 的联通块上,且 n1n-1nn 之间未直接相连,此时答案为 0。如果直接相连,那么其实其他连通块要连接到 nn 的连通块上,这个要怎么算呢?我们不妨参考一下题目中的这个式子。

给定一个含有 nn 个顶点和 mm 条边的森林。假设该森林有 kk 个连通块,其大小分别为 s1,s2,,sks_1, s_2, \dots, s_k。已知将该森林添加 k1k-1 条边使其成为一棵树的方案总数为:

nk2i=1ksin^{k-2} \prod_{i=1}^{k} s_i

实际上这个式子是凯莱公式的推论?

我们先来看一下凯莱公式吧,凯莱公式即:

image

其证明方法有:

image

呃😅,那我们还是用这个 prufer 序列吧,其实 prufer 序列就是把题目中描述的删点过程:每次我们记录一下这个我们删的点的父节点,得到的就是长度为 n2n-2 的 prufer 序列。这个序列有 nn2n^{n-2} 种选择,由于每颗生成树对应的 prufer 序列显然是唯一的,prufer 序列也唯一对应一颗生成树,因此生成树的数量就是 nn2n^{n-2}(这个说的比较粗糙,只是引入一下 prufer 序列这个工具,帮助后面我们的这个理解)。

那么这个连通块的式子是怎么来的?

首先从 prufer 序列的角度来看,那么由于其中的每个点,都可以作为长度为 k2k-2 的 prufer 序列中的点,所以就是 nk2n^{k-2},那么由于每个连通块还需选出来一个代表点连接,因此是:

nk2i=1ksin^{k-2} \prod_{i=1}^{k} s_i

可以想象,nk2n^{k-2} 代表了这个接收端,i=1ksi\prod_{i=1}^{k} s_i 代表了这个发送端。不过还有一个特例,就是没有被 prufer 序列覆盖的根连通块的这个贡献也包含在了这个 i=1ksi\prod_{i=1}^{k} s_i 当中。换句话说,一个长度为 k2k-2 的 prufer 序列的贡献是 i=1ksi\prod_{i=1}^{k} s_i**,原因在于你要确定所有非根连通块的发送端****(**这个是固定的,只有一个的,否则会成环),还要确定根连通块的接收端(在 prufer 中未体现)(严格来讲是最后一个被删除的块所连接的这个根连通块的接收点)。

哎,我们回来看题目:

我们之前所说的结论:

nn 为根,n1n-1 所在的子树的根就是所能留下来的点

说明,n1n-1 连接在 ii 的子树下,是必要条件,是必须满足的。

你就抓住这个,进行分类讨论即可,因为太过细节,这里就不展开了。

然后,你会发现答案不对

1
2
3
4
_______________[ Sample Testcase #1 OUTPUT]_______________
1 2
0 0 0 1
10 0 1 5 5

这道题目的难点,特别是计数难点在于,如何去解决一些先 kk 连通块连上 ii 的子树,然后 n1n-1 再连上 kk 连通块去的这个情况(或者更加复杂情况下的计数)。

具体而言,我们以样例 3 的这个第一个计数为例:

image

但是这个计数问题我们怎么解决?

我们用算概率的方式,得到这个答案,具体而言:

image

为什么我们可以使用算概率的方式呢?实际上,n1n-1 连接到 11 的子树的概率就是 12\frac{1}{2},无论他是通过 33 连接,还是不通过 33 连接,都是这个概率。这个概率就起到了相当于抽丝剥茧,剥开重重迷雾的作用

AC代码

AC

https://codeforces.com/contest/2191/submission/360174534

心路历程(WA,TLE,MLE……)

  • n1n-1 的答案是:

    • 如果 nnn1n-1 直接相连,答案就是 nk2i=1ksin^{k-2} \prod_{i=1}^{k} s_i。如果不直接相连,还处于同一联通块,那么答案是 0。那么最后一种更普遍的情况,就是 nnn1n-1 处于两个连通块,这个时候就将 nnn1n-1 连接在一起,形成的新的森林,用上面那个公式计算即可。
  • 更加普遍的情况下,ii 的答案是:

    • iinn 处于相同连通块:
    • iinn 处于不同连通块:
      我们之前所说的结论:

nn 为根,n1n-1 所在的子树的根就是所能留下来的点
说明,n1n-1 连接在 ii 的子树下,是必要条件,是必须满足的。