【補題記錄】 Codeforces Round 797 (Div. 3) F Shifting String(置換環(huán)類型補題記錄)
Codeforces Round 797 (Div. 3) F Shifting String
思路:
根據(jù)這個排列進行替換的操作可以往置換環(huán)考慮,就是對于每一段字串,它的變換都是有規(guī)律的,經(jīng)過一定的操作之后都會回到原點,可以想象轉(zhuǎn)化成圖上問題。
參考ygg的題解,直接用鏈表模擬這個轉(zhuǎn)化的過程,然后暴力計數(shù),因為要滿足所有點都回到對應原位,所以求所有滿足條件的長度之后求lcm即可
代碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N = 200+10,mod = 1e9+7;
int p[N];
bool v[N];
vector<int> c;
void dfs(int x){//找到完整的一個環(huán)并且存在vector c中
if(v[x])return;
v[x] = 1;
c.push_back(x);
dfs(p[x]);
}
void solve() {
int n;
string s;
cin >> n >> s;
s = " " + s;
for(int i = 1; i <= n; i ++) cin >> p[i],v[i] = 0;
int res = 1;
for(int i = 1; i <= n; i ++){
if(!v[i]){
c.clear();
dfs(i);
list<char> pres,nows;
// for(int j = i; v[j]; v[j] = 1, j = p[j])
// pres.push_back(s[j]);
for(auto id: c) pres.push_back(s[id]);
nows = pres;
nows.push_back(nows.front());//把頭結(jié)點移動到尾部,就是模擬這個環(huán)上的點移動的過程
nows.pop_front();
int t = 1;
while(pres != nows){
nows.push_back(nows.front());
nows.pop_front();
t ++;//不斷重復上述操作然后計數(shù)
}
res = res * t /__gcd(res,t);
}
}
cout << res <<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _t = 1;
cin >> _t;
while(_t --)
solve();
return 0;
}
Educational Codeforces Round 4, E Square Root of Permutation
參考ygg的題解,補充注釋
代碼
#include<bits/stdc++.h>
//#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N = 1e6+10,mod = 1e9+7;
int ans[N],p[N],vis[N],n;
vector<int> c;
vector<vector<int>> cyc[N]; //cyc[i]存的是大小為i的每個環(huán) 每個環(huán)用一個vector來存
void update(vector<int> x){//把環(huán)還原成排列
for(int i = 1; i < x.size(); i++){
ans[x[i-1]] = x[i];
}
ans[x.back()] = x[0];
}
void dfs(int u){
if(vis[u]) return;
vis[u] = 1;
c.push_back(u);
dfs(p[u]);
}
void solve() {
cin >> n;
for(int i = 1; i <= n; i ++) ans[i] = i,cin >> p[i];
for(int i = 1; i <= n;i ++){
if(!vis[i]){
c.clear();
dfs(i);//把排列拆成各種大小的環(huán)
cyc[c.size()].push_back(c);
}
}
for(int sz = 1; sz <= n; sz ++){
if(sz%2 == 0 && cyc[sz].size() % 2 == 1){
cout << "-1\n";
return;
}
}
for(int sz = 1; sz <= n; sz ++){
if(sz%2 == 1){
for(auto c: cyc[sz]){//遍歷大小為奇數(shù)的環(huán)
vector<int> now(c.size());
int id = 0;
for(auto it: c){
now[id % c.size()] = it;
id+=2;
}
update(now);
}
} else {//遍歷大小為偶數(shù)的環(huán)
for(int i = 0; i < cyc[sz].size(); i += 2){
vector<int> c1 = cyc[sz][i],c2 = cyc[sz][i+1];//每次c1,c2代表合成一對的環(huán)
vector<int> now;//now存合成的環(huán),交替放入now中
for(int i = 0; i < c1.size(); i ++){
now.push_back(c1[i]);
now.push_back(c2[i]);
}
update(now);
}
}
}
for(int i = 1; i <= n ;i ++) cout << ans[i] << " ";
cout <<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _t = 1;
//cin >> _t;
while(_t --)
solve();
return 0;
}
Codeforces Round 789 (Div. 2) E Tokitsukaze and Two Colorful Tapes
代碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N = 1e5+10,mod = 1e9+7;
int a[N],b[N],to[N];
bool v[N];
vector<int> c;
void dfs(int x){
if(v[x]) return;
v[x] = 1;
c.push_back(x);
dfs(to[x]);
}
void solve() {
int n;
cin >> n;
for(int i = 1; i<= n;i ++) v[i] = 0;
int mi = 1,mx = n;
for(int i = 1; i<= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i],to[a[i]] = b[i];
int ans = 0;
auto cal=[&](){
if(c.size() == 1) return 0ll;
vector<int> v;
for(int i = 0; i < c.size() - c.size() % 2; i ++){
if(i%2 == 0) v.push_back(mx--);
else v.push_back(mi ++);
}
int res = 0;
// for(auto i:v){
// cout << i <<" ";
// }
// cout << '\n';
for(int i = 1; i < v.size(); i ++) {
res += abs(v[i] - v[i - 1]);
}
res += abs(v.back() - v[0]);
return res;
};
for(int i = 1; i <= n;i ++){
if(!v[i]){
c.clear();
dfs(i);
int k = cal();
//cout << k << "\n";
ans += k;
}
}
cout << ans <<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _t = 1;
cin >> _t;
while(_t --)
solve();
return 0;
}

浙公網(wǎng)安備 33010602011771號