• 【思维】C. Phoenix and Distribution


    C. Phoenix and Distribution

    题意:给定长度为n的字符串s,将s任意拆分成k个部分,求k个部分中字典序最大的最小字典序

    思路:

    因为是任意拆分,所以将s中的字母从小到大排序,那么字典序最小的字母为s[1],记它的个数为p

    实际上要求的还是最小字典序,那么在构造这k个部分的过程中,应始终选用可选的最小字母

    有三种情况:

    1.(p<k),则(k)个部分中必有(p)个以s[1]开头,而第(p+1)个则以更大的字母开头,故第(k)个部分应以s[k]这个字母为开头,那么它一定是字典序最大的那个。由于要求最小字典序,则不应在其后继续接字母,剩余字母都将安排到(p)个部分中。所以答案应该为s[k]

    2.(k≤p<n),则(k)个部分都以s[1]为开头,答案应在后直接接剩下所有的串,就直接能保证满足题意

    3.(p=n),则k个部分平均分配所有字母才能保证答案是最小的字典序,答案应该是(n/k)个s[1]

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 3e5 + 10;
    typedef long long LL;
    LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
    LL lcm(LL a, LL b) {return a * b / gcd(a, b);}
    char s1[100000 + 10];
    int main()
    {
    	int t; cin >> t; while (t--){
    		int n, k;
    		cin >> n >> k;
    		cin >> s1+1;
    		sort(s1+1, s1 + n+1);//找出字典序前k小的字母
    		if (s1[1] != s1[k]) cout << s1[k] << endl;
    		//如果与s1[1]相同的字母小于k个,那么符合要求的答案必为s1[k]这个字母
    		else if (s1[n] != s1[k + 1]) cout << s1[1] << s1 + k + 1 << endl;
    		//如果与s1[1]相同的字母大于等于k个,但不是全部都相同
    		//那么答案以s1[1]开头,后面接从k+1个字母开始的串
    		else {
    			//全部相同,平均分配
    			cout << s1[1];
    			for (int i = 1; i <= (n - 1)/ k; i++) cout << s1[k + 1];
    			cout << endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android之dialog
    android上下文菜单(ContextMenu)
    Android中Handler的使用2
    Intent 各种跳转 .
    Android之Adapter用法总结
    android之Menu 实例与详解
    android学习之FrameLayout
    Andriod: 在xml布局中使用自定义属性
    你软考了吗?
    菜鸟从零学习数据库(三)——存储过程
  • 原文地址:https://www.cnblogs.com/streamazure/p/12891148.html
Copyright © 2020-2023  润新知