1. 解题思路
猜猜题。我们考虑先求出 KKK 再构造。
1.1. 下界
不难发现,相遇的人以后永远不会分开,因此有人的位置数量单调不增。
我们的目标就是让尽可能多的人相遇。反过来想:有没有一些人,无论怎么操作都不可能相遇?
手玩小样例,从简单且对称的开始。玩玩具有循环节的样例,不难发现:如果两个位置正好相差一个循环节长度,那么对应的人永远无法相遇。
设 MMM 为 SSS 的最短循环节长度。
由于 SSS 循环移位 MMM 位后不变,两个位置相差 MMM 的人的视角下 SSS 完全相同。因此每次操作后仍然相差 MMM,永不相遇。
把所有人按照位置 mod M\bmod MmodM 分类,每一类中的人永不相遇,所以至少 N/MN/MN/M 个位置有人。
于是得到答案下界
K≥NM K\ge \frac{N}{M} K≥MN
1.2. 上界
接下来大胆猜测该下界就是答案。
题目限制 L≤106,N≤1000L\le 10^6,N\le 1000L≤106,N≤1000,似乎在暗示构造应该长 N2N^2N2。所以一个很自然的想法是:直接把 SSS 重复 NNN 次,看看能不能达到下界。
以下称一次操作序列 SSS 为“一轮操作”。
从位置 N,N−M,N−2M,…N,N-M,N-2M,\dotsN,N−M,N−2M,… 出发的人,每次都会被带着恰好向前移动 111 格。这些人永不相遇,共有 N/MN/MN/M 个。称这样的人为“A”。其他人为“B”。
我们需要让 B 最终都与 A 相遇。
有如下性质:每一轮操作,每个 B 至少有一次会向前移动 ≥2\ge 2≥2 格。
否则,存在一个 B 在这一轮中每次都只移动 111 格,这意味着从某个不同的起始位置观察到的字符串与 SSS 完全相同,即 SSS 存在 <M<M<M 的循环节,与 MMM 的最小性矛盾。
显然操作都不改变人的相对顺序,一个人不可能越过另一个人而不与其相遇。每轮结束时,A 恰好回到原位,而 B 至少比 A 多前进 111 格。因此只要 B 尚未与 A 相遇,它到前方 A 的距离就至少缩短 111 格。所以经过至多 M−1M-1M−1 轮,所有 B 都会与某个 A 相遇,此时有人位置的数量就变为 N/MN/MN/M,达到下界。
因此
K=NM
\boxed{K=\frac{N}{M}}
K=MN
实际实现时只需要把 SSS 重复 M−1M-1M−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;
}
本题核心在于利用字符串S的最短循环节长度M,证明最优解K等于N/M。通过分析位置模M的等价类,得出下界K≥N/M;再构造S重复M−1次的操作序列,结合相对移动性质证明该下界可达。关键点包括循环节唯一性、操作不改变相对顺序、B类人每轮至少比A类人多进1格,最终在M−1轮内全部相遇。

7157

被折叠的 条评论
为什么被折叠?



