TonyYin's Blog

Back

T1#

题意#

X 和 Y 各有一个权值 vx,vyv_x, v_y.

现在从最低位开始依次比较。

比如 vx=37v_x=37vy=28v_y=28

  • 首先比较最后一位,(7,8)(7,8),Y 暂时领先。
  • 再加上前一位,(37,28)(37,28),X 暂时领先。
  • 比较结束。

如果我们用 X 代表小 X 暂时领先,Y 代表小 Y 暂时领先,那么可以写下一个字符串 XY

再比如,vx=137v_x=137vy=47v_y=47

如果我们再用 Z 表示小 X 与小 Y 的点赞数暂时一样,那么写下的字符串应该为 XYZ

给定最后的字符串 sis_i,请构造一种可能的 (vxvy)(v_x v_y)

若不存在构造方案,输出 1-1.

为了方便输出,用前导零补足位数。

对于 100%100\% 的数据,si{X,Y,Z}s_i \in \{\texttt{X},\texttt{Y},\texttt{Z}\}1len(s)1061 \le \text{len}(s) \le 10^6

XY

37
28
plaintext
XYZ

137
047
plaintext
ZZZZZZ

000000
000000
plaintext
XYZXYZ

-1
plaintext

题解#

如果 ZZ 不是连续的后缀,则无解。

否则用 0/10/1 构造即可。

const int MAXN = 1e6 + 10;
string s;
int a[MAXN], b[MAXN];
int main() {
	cin >> s;
	int n = s.length(), flag = 0;
	for(int i = 0; i < n; i++) {
		if(flag && s[i] != 'Z') {
			cout << -1 << endl;
			return 0;
		}
		if(s[i] == 'X') a[i] = 1, b[i] = 0;
		else if(s[i] == 'Y') a[i] = 0, b[i] = 1;
		else if(s[i] == 'Z') flag = 1;
	}
	for(int i = 0; i < n; i++) cout << a[i]; cout << endl;
	for(int i = 0; i < n; i++) cout << b[i]; cout << endl;
	return 0;
}
cpp

T2#

题意#

给定正整数 nn,请找出一个合法的三元组 (x,y,z)(x, y, z),满足:

1x+1y+1z=2n\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{2}{n}

要求:x,y,zZ+x, y, z\in \Z^+ 且互不相同。

1n1041\leq n\leq 10^4.

题解#

1x+1y+1z=1n+1n\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{n}+\frac{1}{n}

那就直接 z=nz=n,则有:

1x+1y=1n\frac{1}{x}+\frac{1}{y}=\frac{1}{n}

考虑裂项公式:

1n1n+1=1n(n+1)\frac{1}{n}-\frac{1}{n+1}=\frac{1}{n(n+1)}

因此:

1x+1y=1n+1+1n(n+1)\frac{1}{x} + \frac{1}{y}=\frac{1}{n+1}+\frac{1}{n(n+1)}

于是得到:

{x=n+1y=n(n+1)z=n\left\{ \begin{array}{lr} x=n+1\\ y=n(n+1)\\ z=n \end{array} \right.

n=1n=1 时,x=y=n+1x=y=n+1,无解。

否则,按上述方案构造即可。

T3#

题意#

给定一个长度为 nn 的数组 aa

你需要确定一个范围 [x,y][x,y],并将 aa 数组分成 kk 段,使得对于每一段,在范围 [x,y][x,y] 以内的不同元素个数大于在范围 [x,y][x,y] 以外的不同元素个数。

此处的 x,yx, y 都是权值,不是下标。

请求出任意一组使得 (yx)(y-x) 最小的 x,yx,y,并输出划分的方案。

数据范围:

  • tt 组数据,1t3×1041\leqslant t\leqslant 3\times 10^4
  • 1kn2×1051\leqslant k\leqslant n\leqslant 2\times 10^5n2×105\sum n\leqslant 2\times 10^5
  • 1ain1\leqslant a_i\leqslant n

题解#

对于这道题,最根本的问题是最小化的 (yx)(y-x),而具体的形式是如何划分整个序列。

我们可以发现,如果同时考虑这两个问题,事情会变得非常复杂,难以下手。

所以我们不妨暂且扔下具体的形式,去考察最根本的问题。

**性质:**划分为 kk 段时,在 [x,y][x, y] 内的数总体上至少要比在此区间以外的数多 kk 个。

**证明:**每个段内至少多一个,一共多至少 kk 个。

做法:

先将整个序列从小到大排序,然后用一个大小为 nnk2n-\lfloor\frac{n-k}{2}\rfloor 的滑动窗口去检测。

窗口两端的数就是 [x,y][x, y],取 (yx)(y-x) 的最小值即可确定 [x,y][x, y]

推理一下可以发现,让每一段都多一个,可以使滑动窗口尽可能小,这样 (yx)(y-x) 也会相应更小,同时这样的一组 [x,y][x, y] 一定有可行的划分方案。

最后构造方案时也是每一段多一个就划开即可。

T4#

题意#

https://ac.nowcoder.com/acm/contest/11251/D

小红想让你构造一个长度不超过 200000200000 的字符串,其中包含 kkred\texttt {red} 子序列。你能帮帮她吗?

子序列的定义:在原串中必须按顺序,可以不连续。例如,reddd\texttt {reddd} 有3个:reddd\underline{\texttt{red}}\texttt{dd}reded\underline{\texttt{re}}\texttt{de}\underline{\texttt{d}}reded\underline{\texttt{r}}\texttt{ed}\underline{\texttt{ed}}.

若无法构造,输出 1-1,多解输出任意。

数据范围:0k10140\leq k\leq 10^{14}.

题解#

考虑字符串:

rerererererere\texttt{rerererererere}\dots

在第一个 re\texttt{re} 后面加 xxd\texttt{d},可稳定增加 xx 个子序列;

在第二个 re\texttt{re} 后面加 xxd\texttt{d},可稳定增加 3x3x 个子序列;

以此类推,

在第 kkre\texttt{re} 后面加 xxd\texttt{d},可稳定增加 k(k+1)2x\frac{k\cdot (k+1)}{2}x 个子序列。

于是把字符串长度缩小到 n13n^{\frac{1}{3}} 级别,可以证明这样的长度一定小于 200000200000.

#include<bits/stdc++.h>
using namespace std;
int tong[101010];
int main(){
    long long n,i,j,k,p;
    cin>>n;
    if(n==0)return cout<<"d",0;
    for(i=1;i*i*i/6<=n;i++);
    i--;
    for(j=i;j>0;j--){
        tong[j]+=n/(j*(j+1)/2);
        n%=j*(j+1)/2;
    }
    for(j=1;j<=i;j++){
        cout<<"re";
        while(tong[j]--)cout<<"d";
    }
}
cpp

T5#

题意#

Task1:试判断能否构造并构造一个长度为 nn1n1 \dots n排列,满足其 nn前缀和nn 的意义下互不相同。若存在,请给出一种构造方案。

Task2:试判断能否构造并构造一个长度为 nn1n1 \dots n排列,满足其 nn前缀积nn 的意义下互不相同。若存在,请给出一种构造方案。

测试点类型 111010 分,满足 X=1X = 11n101 \leq n \leq 10
测试点类型 224040 分,满足 X=1X = 11n1051 \leq n \leq {10}^5
测试点类型 331010 分,满足 X=2X = 21n101 \leq n \leq 10
测试点类型 444040 分,满足 X=2X = 21n1051 \leq n \leq {10}^5

样例输入 #1#

1 1
8
plaintext

样例输出 #1#

2 8 7 6 5 4 3 2 1
plaintext

样例输入 #2#

2 1
11
plaintext

样例输出 #2#

2 1 2 3 5 10 6 7 4 9 8 11
plaintext

题解#

设序列为 aia_i,分别讨论两个子任务。

Task1#

si=(j=1iai)modns_i=(\sum\limits_{j=1}^i a_i)\bmod n,可以有如下发现:

  1. l,r,slsr(modn)\forall l, r, s_l\equiv s_r\pmod n 当且仅当 srsl10(modn)s_r-s_{l-1}\equiv 0\pmod n. 因此不存在区间 [l,r][l, r] 的区间和是 nn 的倍数。
  2. ai=na_i=n 时,i=1i=1.
  3. 2n2\nmid nn1n\neq 1,无解。

接下来对有解情况进行构造。

发现 nn 必定为偶数,要想让 ss 构成 modn\bmod n 意义下的完全剩余系,考虑把所有偶数在模意义下取相反数。

也就是说,使:

s={0,1,2,3,4,5,,n1}s=\{0, 1, -2, 3, -4, 5, \cdots, n-1\}

注意到,所有偶数的符号为负,再加上 nn 变为正数后,仍为偶数,所以 ss 仍然满足题意。

则有 aia_i 的通项公式:

ai={ni+1,2ii1,2ia_i= \left\{ \begin{array}{lr} n-i+1, &2\mid i\\ i-1, &2\nmid i \end{array} \right.

注意 a1=n0a_1=n\neq 0.

Task2#

si=(j=1iai)modns_i=(\prod\limits_{j=1}^i a_i)\bmod n,可以有如下发现:

  1. l,r,slsr(modn)\forall l, r, s_l\equiv s_r\pmod n 当且仅当 srsl10(modn)\frac{s_r}{s_{l-1}}\equiv 0\pmod n. 因此不存在区间 [l,r][l, r] 的区间积是 nn 的倍数。
  2. ai=na_i=n 时,i=ni=n.
  3. ai=1a_i=1 时,i=1i=1.
  4. nn 为合数时(44 除外),n(n1)!n\mid (n-1)!,所以 sn1sn(modn)s_{n-1}\equiv s_n\pmod n,无合法方案。

因此序列开头为 11,末尾为 nnnn 为质数,想到 si=is_i=i 是否可行?

下面在 si1+1si(modn)s_{i-1}+1\equiv s_i\pmod n 的情况下构造:

si1+1si1×ai(modn)si1×(ai1)1(modn)ai=inv(si1)+1(modn)\begin{aligned} s_{i-1} +1 &\equiv s_{i-1} \times a_i &\pmod{n}\\ s_{i-1} \times (a_i-1) &\equiv 1 &\pmod{n}\\ a_i &= \operatorname{inv}(s_{i-1})+1 &\pmod{n} \end{aligned}

于是可以从头开始递推完成构造。

T6#

题意#

给你 nn整点和它们的坐标,现在给它们分成两组并两两连上边。

对于每条边,如果两端的点在:同一组则边为黄色,不同组则为蓝色

现在让你给出任意一种分组方案,使得所有长度相同的边颜色相同。

保证存在合法方案。

2n1032\leq n\leq 10^3xi,yi106|x_i|, |y_i|\leq 10^6.

题解#

将点分为黑色和白色两组。

考虑对格子黑白染色,坐标和为偶数的染为黑色

一、若两种颜色的点都存在#

黄色边的边长平方一定是奇数,蓝色边的边长平方一定是偶数,满足题目条件。

直接按黑白颜色分组即可。

二、若只存在一种颜色的点#

不妨设只存在黑点,因为只有白点,就可以全部下移一格,转化为黑点。

如果所有点的两维坐标都是偶数,则可以直接 ÷2\div 2,但我们只保证了 2(x+y)2\mid (x+y).

想要转化到让 (x+y)(x+y) 既有奇数又有偶数,过程中不改变点之间的位置关系。

注意到 2(x+y)2(xy)2\mid (x+y)\Rightarrow 2\mid (x-y).

联想到坐标旋转公式:

{x=xcosθysinθy=xsinθ+ycosθ\left\{ \begin{aligned} x^\prime=x\cos \theta-y\sin \theta\\ y^\prime=x\sin \theta+y\cos \theta \end{aligned} \right.

若旋转 45°45\degree,则有:

{x=22x22y=22(xy)y=22x+22y=22(x+y)\left\{ \begin{aligned} x^\prime=\frac{\sqrt{2}}{2}x-\frac{\sqrt{2}}{2}y=\frac{\sqrt{2}}{2}(x-y)\\ y^\prime=\frac{\sqrt{2}}{2}x+\frac{\sqrt{2}}{2}y=\frac{\sqrt{2}}{2}(x+y) \end{aligned} \right.

旋转和缩放都可以保证点间位置关系不变。我们只想看到整数,于是让:

{x=xy2y=x+y2\left\{ \begin{aligned} x^\prime=\frac{x-y}{2}\\ y^\prime=\frac{x+y}{2} \end{aligned} \right.

这样进行若干次,最终一定会使黑白点均存在。

分为了黑白点就可以由之前的方法解决,否则继续递归。

递归的次数为 O(logA)\mathcal O(\log A) 次,其中 AA 为坐标值域大小。

构造专题分享
https://www.tonyyin.top/blog/oi-solution/pre-20220609
Author TonyYin
Published at June 19, 2022
Comment seems to stuck. Try to refresh?✨