1. 程式人生 > 實用技巧 >Codeforces 1367E. Necklace Assembly(思維、gcd)

Codeforces 1367E. Necklace Assembly(思維、gcd)

連結:https://codeforces.com/contest/1367/problem/E
來源:Codeforces

  思路:給你一個長度為 \(n\) 的字串,現在讓你構造一個新的字串 \(str\),這個字串逆時針旋轉 \(t * k\) 個字元,這個字串仍然是 \(str\),求能夠構成新的字串的最大長度。現在我們可以假設這個字串的最大長度為 \(len\),如果我們需要逆時針旋轉以後依然是 \(str\),說明這個字串有一個迴圈節,那麼我們就可以得到這個字串的最小迴圈節為 \(MinLen = gcd(len, k)\),那麼這個字串就有 \(part = strlen(str) / MinLen\)

個迴圈節,此時我們就可以求出把每一個字元分成 \(part\) 組,每一組可以分配多少個字元,最後把每一組的字元的個數相加,如果這個長度大於迴圈節的長度,那麼此時就可以組成一個符合條件的 \(str\)

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 2e5 + 10;
char str[maxn];
int cnt[26];
 
int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;	
}

int main() {
	int T; scanf("%d", &T);
	while(T --) {
		int n, k; scanf("%d%d", &n, &k);
		scanf("%s", str);
		for(int i = 0; i < 26; ++ i) cnt[i] = 0;
		for(int i = 0; i < n; ++ i) cnt[str[i] - 'a'] ++;
		int ans = 0;
		for(int i = 1; i <= n; ++ i) {
			int MinLen = gcd(i, k), part = i / MinLen, resLen = 0;
			for(int j = 0; j < 26; ++ j) resLen += cnt[j] / part;
			if(resLen >= MinLen) ans = i; 
		}
		printf("%d\n", ans);
	}
	return 0;
}