Codeforces Round #650 (Div. 3) E. Necklace Assembly 思维 暴力+二分
Posted cimonhe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #650 (Div. 3) E. Necklace Assembly 思维 暴力+二分相关的知识,希望对你有一定的参考价值。
E. Necklace Assembly
题目大意:
给定一个长度为n的字符串s,和一个数k,从这个字符串s中选择一些字符组成一个周期为k的因子的最大字符串,并输出这个最大字符串的字符数(1<=n,k<=2000),有t组测试数据并且这t组测试数据的n的总数和不超过2000 (1<=t<=100)。
思路:
首先数据范围小 暴力+二分即可。
将每个字母的个数统计出来,枚举每个k的因子,以这些因子作为周期T,二分查找满足周期为T的最大个数。
代码:
#include<bits/stdc++.h> typedef long long ll; using namespace std; #define N 2010 #define M 26 int factor[N],tot; vector <int> v; bool check(int x,int y)//判断能否凑出x个周期为T个字母的数 并且周期 T能否大于y { if (!x) return true; int ans=0; for (auto a:v) ans+=a/x; return ans>=y; } void solve() { int cntletter[M]={0}; v.clear(); int n,k; tot=0; string s; cin>>n>>k; cin>>s; for (int i=2;i<=k;i++) //将k的因子放进factor数组中 if (k%i==0) factor[++tot]=i; for (int i=0;i<s.size();i++) //统计各个字母出现的次数 cntletter[s[i]-‘a‘]++; for (int i=0;i<M;i++) //将各个字母出现次数大于0的数量放进v中 if (cntletter[i]) v.push_back(cntletter[i]); sort(v.begin(),v.end()); //将v从小到大排序 int ans=v.back(); for (int i=1;i<=tot;i++) //以k的各个因子为周期遍历一遍 { int l=0,r=n,mid; int res=0; while (l<=r) //二分查找出以该因子为周期最大的数目 { mid=(l+r)/2; if (check(mid,factor[i])) { res=mid; l=mid+1; } else r=mid-1; } ans=max(ans,res*factor[i]); } cout<<ans<<endl; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; cin>>t; while (t--) solve(); return 0; }
赛后补题:
原作者:https://blog.csdn.net/qq_43627087/article/details/106807131
以上是关于Codeforces Round #650 (Div. 3) E. Necklace Assembly 思维 暴力+二分的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #650 (Div. 3) A. Short Substrings
Codeforces Round #650 (Div. 3) C. Social Distance
Codeforces Round #650 (Div. 3) C. Social Distance (前缀和)
Codeforces Round #436 E. Fire(背包dp+输出路径)