唔。。。。話說好久沒有發佈題解了(手癢癢了
首先特別鳴謝lykkk大佬今天下午教我Manacher算法,甚是感謝
爲了體現學習成果,寫一篇蒟蒻版的題解(大佬勿噴
言歸正傳
題面——>在這兒
首先做這道題要掌握一個算法——Manacher算法
簡要說他就是用來解決迴文串相關問題的算法,並不高深
由題意可知,顯然每一個和諧羣體就是一個長度爲奇數的迴文串
用Manacher可以求每個位置的迴文半徑
因爲我們只要求奇數個的迴文串,那麼顯然我們不需要在字符串裏添加一些無關字符
那麼我們用Manacher求出以當前位置爲中心的最長迴文子串長度
所以我們就會在求的同時搞出最長的len
然後根據對稱性可知也有長爲len*2-1的迴文子串,接着我們只需要統計一下就可以了
注意我們只要奇數個,去掉偶數個
因爲數據範圍過大,所以我們要Fast_Pow使得不會爆掉
那麼。。。下面我們來看一下我優秀的代碼
#include<bits/stdc++.h> using namespace std; #define ll long long const int mod = 19930726; const int N = 1100000; char s[N],str[N*2]; int p[N*2],cnt[N]; int len,n; ll ans=1,k; ll ksm(int x,int y) {//因爲數據範圍很大容易爆掉,所以就要Fast_Pow if(x==1) return 1; ll res=1,base=x; while(y) { if(y&1) res=(res*base)%mod; base=(base*base)%mod; y>>=1; } return res; } void manacher() {//Manacher模板,詳見洛谷P3805 for(int i=1; i<=len; i++) str[i*2-1]='%',str[i*2]=s[i]; str[len=len*2+1]='%'; int id=0,mx=0; for(int i=1; i<=len; i++) { if(i<mx) p[i]=min(p[id*2-i],mx-i); else p[i]=1; while(p[i]+i<=len && i-p[i]>=1 && str[i+p[i]]==str[i-p[i]]) p[i]++; if(p[i]+i>mx) id=i,mx=i+p[i]; if((p[i]-1)%2) cnt[p[i]-1]++; } } int main() { int sum=0; cin>>n>>k>>s+1; len=n; manacher(); for(int i=n; i>=1; --i) {//根據題意常規操作 if(i%2==0) continue; sum+=cnt[i]; if(k>=sum) { ans=(ans*ksm(i,sum))%mod; k-=sum; } else { ans=(ans*ksm(i,k))%mod; k-=sum; break; } } if(k>0) ans=-1; cout<<ans; return 0; }
完結,撒花!!