AtCoder-arc227_c Follow the Letters 题解

1. 解题思路

猜猜题。我们考虑先求出 \(K\) 再构造。

1.1. 下界

不难发现,相遇的人以后永远不会分开,因此有人的位置数量单调不增。

我们的目标就是让尽可能多的人相遇。反过来想:有没有一些人,无论怎么操作都不可能相遇?

手玩小样例,从简单且对称的开始。玩玩具有循环节的样例,不难发现如果两个位置正好相差一个循环节长度,那么对应的人永远无法相遇。

设 \(M\) 为 \(S\) 的最短循环节长度。由于 \(S\) 循环移位 \(M\) 位后不变,两个位置相差 \(M\) 的人的视角下 \(S\) 完全相同。因此每次操作后仍然相差 \(M\),永不相遇。

把所有人按照位置 \(\bmod M\) 分类,每一类中的人永不相遇,所以至少 \(N/M\) 个位置有人。

于是得到答案下界

\[K\ge \frac{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\),达到下界。

因此

\[\boxed{K=\frac{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;
}
posted @ 2026-10-22 21:32  xiaoniu142857  阅读(11)  评论(0)    收藏  举报