0%

题目大意

给定长度为nn的序列aa和正整数mmaa的每个元素都是范围在[0,m][0, m]内的整数。

如果且仅当以下两个条件满足时,序列aa被认为是好的

  • a1<a2<a3<<ana_1<a_2<a_3<\ldots<a_n,并且

  • 1lcm(a1,a2)+1lcm(a2,a3)++1lcm(an1,an)+1lcm(an,a1)1\frac{1} {\operatorname{lcm}(a_1,a_2)}+\frac{1} {\operatorname{lcm}(a_2,a_3)}+\ldots+\frac{1} {\operatorname{lcm}(a_{n-1},a_n)}+\color{red} {\frac{1} {\operatorname{lcm}(a_n,a_1)}}\ge1.^{\text{∗}}

你需要用范围在[1,m][1, m]内的整数替换aa中的所有零。计算替换零的不同方式的数量,使得得到的序列aa好的

998244353998\,244\,353取模后输出答案。

^{\text{∗}}两个正整数的最小公倍数(lcm\operatorname{lcm})是能同时整除它们的最小正整数。例如,lcm(2,3)=6,lcm(4,6)=12\operatorname{lcm}(2,3)=6, \operatorname{lcm}(4,6)=12

思路讲解

AC代码

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

题目大意

题目总结:Majority Wins?

1. 目标

给定一个长度为 nn 的二进制字符串 ss,通过最少总代价的操作将其最终转化为一个只包含字符 1 的字符串(即长度为 1 且内容为 1)。

2. 操作定义

在当前字符串中选择一段连续的子串 g[lr]g[l \dots r],计算其中 01 出现的次数:

  • 如果某个字符出现的次数 不少于 另一个字符(即出现次数 \ge 另一方),则可以用该字符替换掉整个子串。

  • 操作代价:等于该子串的长度,即 rl+1r - l + 1

  • 你可以进行多次操作,每次操作后的字符串长度会缩短。

例如,字符串010010可以通过用成本为44的操作将子串1001替换为1来在一次操作中转换为010;字符串1111可以通过在整个字符串上执行成本为44的操作转换为1;字符串0100可以通过取子串100转换为00。

3. 输出要求

  • 输出将字符串转化为 1 的最小总代价。

  • 如果无法转化,则输出 1


样例解释

  • 样例 1 (0):由于只有一个 0,无法通过任何操作产生 1。输出 1

  • 样例 2 (1):已经是 1,无需操作。输出 0

  • 样例 4 (10):选择子串 10(长度 2),其中 1 的数量(1个)不少于 0 的数量(1个),可替换为 1。代价为 2

  • 样例 5 (010)

    1. 选择子串 01 替换为 1,字符串变为 10,代价为 22
    2. 选择子串 10 替换为 1,代价为 22
    3. 总代价 2+2=42 + 2 = 4
  • 样例 6 (00111000)

    1. 选择子串 001111 占多数)替换为 1,字符串变为 1000,代价 55
    2. 选择子串 101 不少于 0)替换为 1,字符串变为 100,代价 22
    3. 再次对 10 进行操作变为 1,字符串变为 1,代价 22
    4. 总代价 5+2+2=95 + 2 + 2 = 9

思路讲解

其实这道题目就是一个分类讨论,感觉放在 C 也没什么问题。

  1. E was proposed as C, and C as B

不难发现,答案再大,不会超过 n+3n+3

image

然后直接输出 nn 的情况就是 1 的数量大于等于 0 的数量的时候。

输出 n+1n+1 是什么情况呢?首先 01 串首部或者尾部为 1 时,输出这个 n+1n+1

还有就是当存在一个位置,使得 suf(1)suf(0)+1\text{suf}(1)≥\text{suf}(0)+1 数量的时候(这个是因为多容纳一个 0 也没事)(suf(x)\text{suf}(x) 代表该位置后缀 xx 数量)。

同理可得 pre(1)pre(0)+1\text{pre}(1)≥\text{pre}(0)+1

那么什么时候输出这个 n+2n+2 呢?当存在一个位置,使得 suf(1)suf(0)\text{suf}(1)≥\text{suf}(0) 数量的时候(表示肯定有 0 嘛,那么我们不妨消掉一个,就可以回到上面一种情况)。

同理可得 pre(1)pre(0)\text{pre}(1)≥\text{pre}(0)

其他情况,就输出 n+3n+3

然后,你忐忑地提交了,发现 WA 了,为什么呢?对拍!

1
2
3
1
10
0000110000

该样例也应该输出这个 n+2n+2,但是我们输出了 n+3n+3,这个是因为什么呢?

image

我们发现 ‘11' 这个东西非常特殊,可以压制两边的 0,你会发现,‘101’ 就不可以压制两边的 0 了。

因此,只要找到 ‘11' 那么答案不会大于 n+2n+2

1
2
3
if (s.find("11")!=string::npos) {
ans=min(ans,N+2);
}

再次忐忑地提交,你发现竟然过了?

AC代码

AC

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

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

题目大意

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……)