标签:首尾相接 num2 cir 恢复原状 LL vis int 数组 cur
对于一个首尾相接的数组,设其旋转k1、k2、k3...次后可以恢复原状。
且k1<k2<k3<...。
则可以肯定,k1为这个数组的循环节,且k2、k3...均为k1的倍数。
一种求循环节的方法为:
对长度为n的循环字符串,先从小到大遍历可能的循环节的长度i,判断是否n%i==0,然后对其中的除第一个循环节内的每一个字符进行判断
参考代码如下(By * A_G, contest: Codeforces Round #797 (Div. 3), problem: (F) Shifting String)
int period(string& s) { int n = s.size(); for (int i = 1; i <= n/2; i++) { if (n%i == 0) { bool good = 1; for (int j = i; j < n; j++) { if (s[j-i] != s[j]) { good = 0; break; } } if (good) return i; } } return n; }View Code
例题 Codeforces Round #797 (Div. 3) F. Shifting String
https://codeforces.com/contest/1690/problem/F
代码如下
#include<bits/stdc++.h> using namespace std; typedef long long LL; LL gcd(LL num1, LL num2) { if (num1%num2 == 0) return num2; return gcd(num2, num1%num2); } void YD() { int n; cin >> n; string str; cin >> str; vector<int> p(n); for (int i = 0; i < n; i++) { cin >> p[i]; p[i]--; } vector<bool> vis(n,false); LL ans = 1; for (int i = 0; i < n; i++) { if (!vis[i]) { string cir; cir+=(str[i]); vis[i] = true; int cur = p[i]; while (cur != i) { cir += (str[cur]); vis[cur] = true; cur = p[cur]; } int nn = cir.size(); for (int ii = 1; ii <= nn / 2; ii++) { if (nn%ii == 0) { bool flag = true; for (int jj = ii; jj < nn; jj++) { if (cir[jj] != cir[jj - ii]) { flag = false; break; } } if (flag) { nn = ii; break; } } } ans = ans / gcd(ans, LL(nn))*LL(nn); } } cout << ans << endl; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); int T; cin >> T; while (T--) { YD(); } }View Code
标签:首尾相接,num2,cir,恢复原状,LL,vis,int,数组,cur 来源: https://www.cnblogs.com/ydUESTC/p/16364357.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。