CF1863C MEX Repetition
思路
乍一看,感觉无从下手,于是就先列举了几个例子:
02 10 21 02 013 201 320 132 013 12345 01234 50123 45012 34501 23450 12345
容易发现周期是 n+1,下面解释理由:
首先因为数量 n,且两两各不相同,而值域是 [0,n],所以在 [0,n] 中,每个数最多存在一个,且有一个数是不存在的,我们假设是 p。
那么对于 a1,第一次一定变为 p,于是这个数列中不存在的数就变成原来的 a1 了,所以 a2 就会变成原来的 a1,以此类推,第一次操作后,等于是把数组最后一位删去,整体往后挪一位,然后把第一位变成 p。
就这样不断地操作,经过 n 次,p 就会被挪到最后一位,然后下一次就会变为原样,所以周期是 n+1。
但是发现直接暴力还是会 TLE,所以做法肯定还要文雅些,既然都在之前找到规律了,我们就可以用上面的规律。
假设 k 是取模后的 k,那么第 k 为一定是 p,对于 k 前面的位置,应该就是原数组的后半段,比如,第 k−1 就是 an,所以可以直接计算得到原数组的位置,对于 k 后面的位置,也可以同理推出对应的原数组的位置。
AC code
#include <bits/stdc++.h> using namespace std; int T,n,k,a[100005]; set<int>s; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k),k%=n+1; for(int i=0;i<=n;++i) s.insert(i); for(int i=1;i<=n;++i) scanf("%d",&a[i]),s.erase(a[i]); auto i=s.begin();int p=*i; if(!k){for(int i=1;i<=n;++i) printf("%d ",a[i]);puts("");} else { for(int i=1;i<=n;++i) { if(i<k) printf("%d ",a[n-k+i+1]); else if(i==k) printf("%d ",p); else printf("%d ",a[i-k]); } puts(""); } s.erase(p); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】