CodeForces - 1553E Permutation Shift(暴力+置换群求环)
題目鏈接:點擊查看
題目大意:假設初始時的數組為 [1,2,3,...,n][1,2,3,...,n][1,2,3,...,n],同時 kkk 為偏移量,則原數組會循環右移 kkk 個單位,假設 k=3,n=5k=3,n=5k=3,n=5,則偏移后的數組為 [3,4,5,1,2][3,4,5,1,2][3,4,5,1,2]
現在給出一個數組,問能否通過至多 mmm 次交換,使得其變成偏移 kkk 個單位后的數組,如果可以的話,哪些 kkk 是符合條件的
題目分析:假設 kkk 是固定的,就變成了經典的置換群求換問題。簡單說一下就是,我們最終的目標是需要得到 nnn 個自環,假設現在的置換群中有 ttt 個環,每次交換可以使得自環的個數增加 111,所以至少需要 n?tn-tn?t 次交換才能達到目標。這個可以 O(n)O(n)O(n) 去解決。
所以一個 O(n2)O(n^2)O(n2) 的解決方法就出來了,比賽的時候也是感覺可能存在著優化的思路但是自己不會就下機了。賽后看了題解發現就是多了個剪枝而已
假設我們至多可以交換 mmm 次,那么最多會影響到 2?m2*m2?m 個環,也就是說初始時就需要有 n?2?mn-2*mn?2?m 個自環才行。設 cnt[k]cnt[k]cnt[k] 是偏移量為 kkk 時的自環個數,不難看出 ∑cnt[i]=n\sum cnt[i]=n∑cnt[i]=n。又因為 m≤n3m\le \frac{n}{3}m≤3n?,所以 cnt[k]≥n?2?mcnt[k]\ge n-2*mcnt[k]≥n?2?m 即 cnt[k]≥n3cnt[k]\ge \frac{n}{3}cnt[k]≥3n?,所以這樣的 kkk 最多有 333 個
剩下的暴力就可以了
代碼:
// Problem: E. Permutation Shift // Contest: Codeforces - Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2) // URL: https://codeforces.com/contest/1553/problem/E // Memory Limit: 256 MB // Time Limit: 3000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) (x&-x) using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; int p[N],a[N],cnt[N],n,m; bool vis[N]; bool check(int k) {int tot=0;for(int i=k+1;i<=n;i++) {p[++tot]=a[i];}for(int i=1;i<=k;i++) {p[++tot]=a[i];}int ans=n;memset(vis,false,n+5);for(int i=1;i<=n;i++) {if(vis[i]) {continue;}ans--;int pos=i;while(!vis[pos]) {vis[pos]=true;pos=p[pos];}}return ans<=m; } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--) {read(n),read(m);memset(cnt,0,sizeof(int)*(n+5));for(int i=1;i<=n;i++) {read(a[i]);cnt[(i-a[i]+n)%n]++;}vector<int>ans;for(int i=0;i<n;i++) {if(cnt[i]>=n-2*m&&check(i)) {ans.push_back(i);}}printf("%d",(int)ans.size());for(auto it:ans) {printf(" %d",it);}puts("");}return 0; }總結
以上是生活随笔為你收集整理的CodeForces - 1553E Permutation Shift(暴力+置换群求环)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021牛客多校1 - Journey
- 下一篇: CodeForces - 1553F P