AtCoder-arc227_c Follow the Letters 题解
1. 解题思路
猜猜题。我们考虑先求出 \(K\) 再构造。
1.1. 下界
不难发现,相遇的人以后永远不会分开,因此有人的位置数量单调不增。
我们的目标就是让尽可能多的人相遇。反过来想:有没有一些人,无论怎么操作都不可能相遇?
手玩小样例,从简单且对称的开始。玩玩具有循环节的样例,不难发现如果两个位置正好相差一个循环节长度,那么对应的人永远无法相遇。
设 \(M\) 为 \(S\) 的最短循环节长度。由于 \(S\) 循环移位 \(M\) 位后不变,两个位置相差 \(M\) 的人的视角下 \(S\) 完全相同。因此每次操作后仍然相差 \(M\),永不相遇。
把所有人按照位置 \(\bmod M\) 分类,每一类中的人永不相遇,所以至少 \(N/M\) 个位置有人。
于是得到答案下界
1.2. 上界
接下来大胆猜测该下界就是答案。
题目限制 \(L\le 10^6,N\le 1000\),似乎在暗示构造应该长 \(N^2\)。所以一个很自然的想法是:直接把 \(S\) 重复 \(N\) 次,看看能不能达到下界。
以下称一次操作序列 \(S\) 为“一轮操作”。
从位置 \(N,N-M,N-2M,\dots\) 出发的人,每次都会被带着恰好向前移动 \(1\) 格。这些人永不相遇,共有 \(N/M\) 个。称这样的人为“A”,其他人为“B”。
我们需要让 B 最终都与 A 相遇。
有如下性质:每一轮操作,每个 B 至少有一次会向前移动 \(\ge 2\) 格。
否则,存在一个 B 在这一轮中每次都只移动 \(1\) 格,这意味着从某个不同的起始位置观察到的字符串与 \(S\) 完全相同,即 \(S\) 存在 \(<M\) 的循环节,与 \(M\) 的最小性矛盾。
显然操作都不改变人的相对顺序,一个人不可能越过另一个人而不与其相遇。每轮结束时,A 恰好回到原位,而 B 至少比 A 多前进 \(1\) 格。因此只要 B 尚未与 A 相遇,它到前方 A 的距离就至少缩短 \(1\) 格。所以经过至多 \(M-1\) 轮,所有 B 都会与某个 A 相遇,此时有人位置的数量就变为 \(N/M\),达到下界。
因此
实际实现时只需要把 \(S\) 重复 \(M-1\) 遍就足够了。
2. 代码
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i(a);i<b;++i)
using namespace std;
int n,m; // m为循环节长度
string s;
bool check(const string &s,int len){
string base=s.substr(0,len);
for(int i=len;i<s.size();i+=len) if(s.substr(i,len)!=base) return false;
return true;
}
signed main(){
cin>>n>>s;
m=n;
rep(i,1,n) if(n%i==0&&check(s,i)){
m=i;
break;
}
cout<<n/m<<'\n'<<n*(m-1)<<'\n';
rep(i,0,m-1) cout<<s;
return 0;
}

浙公网安备 33010602011771号