[BZOJ 2160] 拉拉队排练 Manacher+贪心
来源:互联网 发布:himall 2.6 完整源码 编辑:程序博客网 时间:2024/05/29 17:11
题目传送门:【BZOJ 2160】
题目大意:……拉拉队的选拔工作已经结束,在雨荨的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。这n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。
雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前 K 个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以 19930726 的余数是多少就行了。
输入的第一行为两个正整数 n 和 K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
输出为一个整数,代表题目描述中所写的乘积除以 19930726 的余数,如果总的和谐小群体个数小于K,输出一个整数-1。( n ≤
题目分析:
题目看起来很长,不过压缩后,就是求最长的 k 个回文子串长度的乘积。求出回文子串的长度,直接使用 Manacher 即可,同时统计每个长度出现的次数(O( n )),存放到一个新的值域数组中。之后,再从大到小贪心地选择这些数相乘并取模,就能得到答案。
例如,对于一个字符串 ababcba,我们跑完一遍 Manacher 之后,将它们的回文长度存在新的数组 val 中,此时 val[]={ 0 , 7 , 0 , 3 , 0 , 1 , 0 , 0 , …… },意为:长度为 1 的回文子串有 7 个,长度为 3 的回文子串有 3 个,长度为 5 的回文子串有 1 个(长度为偶数的不予考虑)。然后根据 k 的大小从最长的长度开始依次往下乘。如果取的次数小于 k,那么说明不符合情况,直接输出 -1;否则就输出答案。
下面附上代码:
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- const int MX = 1000005;
- const long long MOD = 19930726LL;
- int n,mr,id,pal[MX],len = 0; //pal:对应位置的回文子串半径
- char ori[MX]; //val:对应位置的回文子串长度
- long long geshu[MX],val[MX],maxv = 0,k; //geshu:各个长度的回文子串的个数
- long long mypow(int a,int b){ //快速幂
- long long res = 1,base = a;
- while (b){
- if (b & 1) res *= base % MOD,res %= MOD;
- base *= base % MOD;
- base %= MOD;
- b >>= 1;
- }
- return res % MOD;
- }
- void manacher(){
- for (int i = 1;i <= len;i++){
- if (i < mr) pal[i] = min(pal[2 * id - i],mr - i);
- else pal[i] = 1;
- while (ori[i - pal[i]] == ori[i + pal[i]]){
- pal[i]++;
- }
- if (i + pal[i] > mr) mr = i + pal[i],id = i;
- val[i] = pal[i] * 2 - 1;
- if (val[i] > maxv) maxv = val[i];
- geshu[val[i]]++; //对应长度的字符串数量 +1
- }
- }
- long long greed(){ //贪心,从大到小计算
- long long ans = 1;
- long long left = k,cur = 0;
- for (int i = maxv;i > 0;i -= 2){
- geshu[i] += geshu[i + 2];
- }
- for (int i = maxv;i > 0;i -= 2){
- if (left - geshu[i] >= 0){
- left -= geshu[i];
- cur = geshu[i];
- }
- else{
- cur = left;
- left = 0;
- }
- ans *= mypow(i,cur)%MOD;
- ans %= MOD;
- }
- if (left > 0) return -1; //小于k,返回-1,否则返回ans
- return ans;
- }
- int main(){
- cin>>n>>k;
- scanf(”%s”,ori + 1);
- len = strlen(ori + 1);
- ori[0] = ’+’;
- ori[len + 1] = ’-‘;
- manacher();
- printf(”%lld”,greed());
- return 0;
- }
- [BZOJ 2160] 拉拉队排练 Manacher+贪心
- BZOJ 2160: 拉拉队排练 manacher
- BZOJ 2160 拉拉队排练 Manacher + 前缀和
- [BZOJ]2160 拉拉队排练 Manacher+快速幂
- BZOJ 2160 拉拉队排练
- BZOJ 2160: 拉拉队排练
- BZOJ 2160: 拉拉队排练
- bzoj 2160 拉拉队排练
- bzoj 2160: 拉拉队排练 (manacher+前缀和+快速幂)
- BZOJ 2160 拉拉队排练 (Manacher 序列差分)
- 【bzoj2160】拉拉队排练 manacher
- [BZOJ 2160] 拉拉队排练 (manacher+差分数组+前缀和)
- 【BZOJ 2160】拉拉队排练 回文树
- bzoj 2160: 拉拉队排练 manachar+快速幂
- BZOJ2160 拉拉队排练 [manacher][前缀]
- HYSBZ 2160 拉拉队排练
- 2160: 拉拉队排练
- 回文树——BZOJ 2160: 拉拉队排练
- linux驱动学习笔记1(简单实现open,read,write,ioctl)
- hdu 2112 HDU Today
- 获取拼音首字母
- Qt: windeployqt命令使用
- 理解word2vec的训练过程
- [BZOJ 2160] 拉拉队排练 Manacher+贪心
- More is better
- pandas入门——数据分组
- ibatis打印sql日志的方法
- android Bluetooth UUID和SDP
- 【java设计模式】之 模板方法(Template Method)模式
- Oracle创建表空间
- 拷贝(复制)结构函数的调用及其作用
- HttpClient跨项目(服务端)调用方法例子