Codeforces Round #650 (Div. 3) E. Necklace Assembly(枚举+二分)

题目链接:https://codeforces.com/contest/1367/problem/E

思路:

    不难想象,这是一道跟循环节有关的问题。k是necklace的周期,这个说法等价于存在k的因数d,使得d是整条necklace的周期。这样,问题转化如下:构造循环节长度为d的necklace,使得其长度最大。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn 100010
#define mod 1000000007
#define ll long long
using namespace std;

int n, k;
char s[2010];
int cnt[30];
bool cmp(int a, int b) {
	return a > b;
}

//x循环节数目
//y周期数&循环节长度
bool can(int x,int y) {
	int i;
	int sum = 0;
	for (i = 1; i <= min(26, y); i++) {
		sum += cnt[i] / x;
	}
	if (sum >= y)return true;
	else return false;
}
//二分查找最大的循环节数目
//x循环节长度
//mid循环节数目
int len(int x) {
	int i, maxlen = 0;
	int l, r, mid;
	l = 1; r = n / x;
	while (l < r) {
		mid = (l + r + 1) / 2;
		if (can(mid,x)) {
			l = mid;
		}
		else {
			r = mid - 1;
		}
	}
	return r * x;
}

int main() {
	int t, i, j;
	cin >> t;
	while (t--) {
		cin >> n >> k;
		scanf("%s", s);
		memset(cnt, 0, sizeof(cnt));
		//统计字符个数
		for (i = 0; i < n; i++)cnt[s[i] - 'a' + 1]++;
		//由大到小排序
		sort(cnt + 1, cnt + 1 + 26, cmp);
		int ans = 0;
		//枚举因数
		for (i = 1; i <= sqrt(k + 0.5); i++) {
			if (k%i == 0) {
				j = k / i;
				if (i <= n)ans = max(ans, len(i));
				if (j <= n)ans = max(ans, len(j));
			}
		}
		cout << ans << endl;
	}

	return 0;
}

 

你可能感兴趣的:(枚举,二分答案)