本文主要是介绍BZOJ2160 拉拉队排练(回文树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
HYSBZ - 2160
Time Limit: 10000MS | Memory Limit: 265216KB | 64bit IO Format: %lld & %llu |
Description
艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。
Input
输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
Output
输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。
Sample Input
5 3 ababa
Sample Output
45 【样例说明】 和谐小群体女生所拿牌子上写的字母从左到右按照女生个数降序排序后为ababa, aba, aba, bab, a, a, a, b, b,前三个长度的乘积为。
Hint
总共20个测试点,数据范围满足:
Source
统计不同回文出现的次数.排序之后快速幂.
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
typedef long long ll;
const int N = 26;
const int MAXN = 1e6 +20;
const int mod = 19930726;
typedef pair<int,int> Node;
struct Palindromic_Tree {int next[MAXN][N] ;int fail[MAXN],cnt[MAXN],len[MAXN],S[MAXN];int last,n,p;int newnode(int l){for(int i = 0; i < N; ++i) next[p][i] = 0;cnt[p] = 0;len[p] = l;return p++;}void init(){last = n = p = 0;S[0] = -1;newnode(0);newnode(-1);fail[0] = 1;fail[1] = 0;}int get_fail(int x){while(S[n-len[x]-1] != S[n]) x = fail[x];return x;}void add(int c){c -= 'a';S[++n] = c;int cur = get_fail(last);if(!next[cur][c]) {int now = newnode(len[cur]+2);fail[now] = next[get_fail(fail[cur])][c];next[cur][c] = now;}++cnt[last = next[cur][c]];}void count(){for(int i = p-1; i >= 0; --i) cnt[fail[i]] += cnt[i];}
} ;
Palindromic_Tree T;
char s[MAXN];
ll quickExp(int a,int n)
{ll res = 1,b = a;while(n) {if(n&1) res = res*b % mod;b = b*b % mod;n >>=1;}return res;
}
Node a[MAXN];
void solve (ll n,ll k) {T.init () ;for(int i = 0; i < n; ++i) T.add ( s[i] ) ;T.count();int m = 0;for(int i = T.p-1; i > 1; --i) {if(T.len[i]&1)a[m++] = (Node){T.len[i],T.cnt[i]};}sort(a,a+m,greater<pair<int,int> >());ll ans = 1;for(int i = 0; k&&i < m; ++i) {int limt = min(k,a[i].se+0LL);k -= limt;ans = ans * quickExp(a[i].fi,limt) % mod;}if(k) ans = -1;printf("%lld\n",ans);
}
int main()
{ll n,k;while(~scanf("%lld%lld%s",&n,&k,s)) solve(n,k);return 0;
}
这篇关于BZOJ2160 拉拉队排练(回文树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!