BZOJ_2160_拉拉隊排練_manacher
阿新 • • 發佈:2018-06-02
cpp namespace 隨著 小夥子 mod -i bzoj amp sam
ababa
BZOJ_2160_拉拉隊排練_manacher
Description
艾利斯頓商學院籃球隊要參加一年一度的市籃球比賽了。拉拉隊是籃球比賽的一個看點,好的拉拉隊往往能幫助球隊增加士氣,贏得最終的比賽。所以作為拉拉隊隊長的楚雨蕁同學知道,幫助籃球隊訓練好拉拉隊有多麽的重要。拉拉隊的選拔工作已經結束,在雨蕁和校長的挑選下,n位集優秀的身材、舞技於一體的美女從眾多報名的女生中脫穎而出。這些女生將隨著籃球隊的小夥子們一起,和對手抗衡,為艾利斯頓籃球隊加油助威。一個陽光明媚的早晨,雨蕁帶領拉拉隊的隊員們開始了排練。n個女生從左到右排成一行,每個人手中都舉了一個寫有26個小寫字母中的某一個的牌子,在比賽的時候揮舞,為小夥子們吶喊、加油。雨蕁發現,如果連續的一段女生,有奇數個,並且他們手中的牌子所寫的字母,從左到右和從右到左讀起來一樣,那麽這一段女生就被稱作和諧小群體。現在雨蕁想找出所有和諧小群體,並且按照女生的個數降序排序之後,前K個和諧小群體的女生個數的乘積是多少。由於答案可能很大,雨蕁只要你告訴她,答案除以19930726的余數是多少就行了。
Input
輸入為標準輸入。第一行為兩個正整數n和K,代表的東西在題目描述中已經敘述。接下來一行為n個字符,代表從左到右女生拿的牌子上寫的字母。
Output
輸出為標準輸出。輸出一個整數,代表題目描述中所寫的乘積除以19930726的余數,如果總的和諧小群體個數小於K,輸出一個整數-1。
Sample Input
5 3ababa
Sample Output
45
一開始看錯題了,以為要奇偶分開討論。。代碼就寫成那樣了。
本題只考慮長度為奇數的回文串。
manacher過程中求極長回文子串然後區間加差分一下。
剩下的就是模擬了。
代碼:
#include <cstdio> #include <string.h> #include <algorithm> using namespace std; typedef long long ll; #define mod 19930726 #define N 1000050 int c[N],p[N<<1],a[N<<1],n,d[N],e[N]; char w[N<<1]; ll K; ll qp(ll x,ll y) { ll re=1; for(;y;y>>=1ll,x=x*x%mod) if(y&1ll) re=re*x%mod; return re; } int main() { scanf("%d%lld",&n,&K); int i; scanf("%s",w+1); for(i=1;i<=n;i++) a[2*i-1]=‘$‘,a[2*i]=w[i]; n=n<<1|1; a[n]=‘$‘; int mx=0,lst; for(i=1;i<=n;i++) { if(i<=mx) p[i]=min(p[2*lst-i],mx-i+1); else p[i]=1; while(i-p[i]>=1&&i+p[i]<=n&&a[i-p[i]]==a[i+p[i]]) p[i]++; if(mx<i+p[i]-1) {mx=i+p[i]-1; lst=i;} int lim=(i+p[i]-2)/2-(i-p[i]+2)/2+1; if(i%2==0) { d[1]++; d[(lim+1)/2+1]--; }else { e[1]++; e[lim/2+1]--; } } n>>=1; ll sum=0; for(c[1]=sum=d[1],i=3;i<=n;i+=2) { c[i]=c[i-2]+d[(i+1)>>1]; sum+=c[i]; } for(i=2;i<=n;i+=2) { c[i]=c[i-2]+e[i>>1]; } if(sum<K) { puts("-1"); return 0; } ll ans=1; i=n; if(n%2==0) i--; for(;i>=1;i-=2) { // printf("%d\n",c[i]); if(K<=c[i]) { printf("%lld\n",ans*qp(i,K)%mod); return 0; } K-=c[i]; ans=ans*qp(i,c[i])%mod; } }
BZOJ_2160_拉拉隊排練_manacher