BZOJ 2160 Manacher 解题报告
来源:互联网 发布:软件编程师 编辑:程序博客网 时间:2024/06/08 23:41
2160: 拉拉队排练
Description
艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。
Input
输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
Output
输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。
Sample Input
5 3
ababa
Sample Output
45
【解题报告】
题目大意是,给出一个长度为n的字符串,求最长的k个回文子串(此题中的回文子串指长为奇数的回文子串)长度的乘积。模19930726后输出,若没有k个则输出-1。(n<=10e6,k<=10e12)
所以首先可以用manacher算法确定每个位置的回文半径, 由于这里只需要长度是奇数, 所以不需要插入‘#’, 直接在首尾添加好不同字符之后跑一遍manacher算法。 对于位置i为中心的回文半径pal[i], 用dp[i]来表示相邻长度的回文串的数量差分(其实就是一个常用的前缀和技巧, 因为这里每次更新[1, pal[i]]这个区间 + 1, 而只在所有更新完毕之后才查询所以没有必要使用树状数组, 直接根据每次更新的时候dp[1]++, dp[R[i] + 1]–, 最后后dp[1~i]的和就是最终ans[i]的值, 即长度为2*i - 1的回文串的数量
然后用快速幂就可以了
代码如下:
/************************************************************** Problem: 2160 User: onepointo Language: C++ Result: Accepted Time:548 ms Memory:21328 kb****************************************************************/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 1000010#define ll long long#define Mod 19930726char s[N];int n,pal[N];ll k,dp[N],ans[N];ll quick_pow(ll base,ll pow) { ll ret=1; while(pow) { if(pow&1) ret=(ret*base)%Mod; pow>>=1;base=base*base%Mod; } return ret; } void manacher(){ int len=n; int id=0,mx=0; s[0]='+',s[len+1]='-'; for(int i=1;i<=len;++i) { if(mx>i) pal[i]=min(mx-i,pal[id*2-i]); else pal[i]=1; while(s[i-pal[i]]==s[i+pal[i]]) ++pal[i]; if(mx<pal[i]+i) mx=pal[i]+i,id=i; } }int main(){ scanf("%d%lld",&n,&k); scanf("%s",s+1); manacher(); memset(dp,0,sizeof(dp)); memset(ans,0,sizeof(ans)); for(int i=1;i<=n;++i) { dp[1]++; dp[pal[i]+1]--; } int maxlen=0; for(int i=1;i<=(n+1)>>1;++i) { ans[i]=ans[i-1]+dp[i]; if(ans[i]>0) maxlen=i; } ll result=1; int r=maxlen; while(r&&k>0) { result=(result*quick_pow((ll)(2*r-1),min(ans[r],k)))%Mod; k-=ans[r];--r; } (k>0)?printf("-1\n"):printf("%lld\n",result); return 0; }
- BZOJ 2160 Manacher 解题报告
- BZOJ 3790 Manacher 解题报告
- BZOJ 2565 Manacher 解题报告
- POJ 3974 Manacher 解题报告
- HDU 3294 解题报告 Manacher 算法
- POJ3974 Palindrome 解题报告【字符串】【Manacher】
- BZOJ 1588 TREAP 解题报告
- bzoj 3223 splay 解题报告
- BZOJ 3223 Splay 解题报告
- BZOJ 3224 TREAP 解题报告
- BZOJ 1820 DP 解题报告
- BZOJ 2144 LCA 解题报告
- BZOJ 4152 博弈论 解题报告
- BZOJ 1566 DP 解题报告
- BZOJ 3119 贪心 解题报告
- bzoj 1036 树链剖分 解题报告
- bzoj 3696 化合物 解题报告
- BZOJ 2563 贪心 解题报告
- Caffe模型转换成tensorflow模型
- 迭代法求平方根
- JS处理字符串及表表单
- 嵌入式工具——strace
- left join、inner join效率对比
- BZOJ 2160 Manacher 解题报告
- numpy
- jquery实现复选框打勾全选,其中一个子复选框不勾中,则不全选。所有子复选框全勾中则又全选。
- 如何使用vim查找字符,及设置查找字符高亮和取消查找字符高亮
- Retrofit2简单使用
- C++ 对象的内存布局(上)
- 小白对C#泛型的理解
- 事务的原理 学习笔记
- 20个常用的java代码片段