/ * 先来一波像题面一样辣眼睛的骚粉色 * /
Description
艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。
Input
输入为标准输入。第一行为两个正整数n和K,代表的东西在题目描述中已经叙述。接下来一行为n个字符,代表从左到右女生拿的牌子上写的字母。
Output
输出为标准输出。输出一个整数,代表题目描述中所写的乘积除以19930726的余数,如果总的和谐小群体个数小于K,输出一个整数-1。
Sample Input
5 3
ababa
WA点:
啊这道题真是气哭,wa了半天最后发现时long long 的问题。
先复习一下基础知识:
unsigned int 0~4294967295
int 2147483648~2147483647
unsigned long 0~4294967295
long 2147483648~2147483647
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:1844674407370955161
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615
按理说这道题除k以外不会爆int 啊,不懂不懂,反正以后看着数大就开long long吧(好草率)
思路:
先来一波manacher,这道题只要求奇数所以在字符串中不用插入‘#’,再用差分统计出每种长度的回文串个数。要注意回文串的长度为奇数所以
if(i%2&&sum[i])
要判断i%2
最后统计的时候记得用快速幂
代码:
/****************************************************
Problem: 2160
User: DD_D
Language: C++
Result: Accepted
Time:260 ms
Memory:13516 kb
*****************************************************/
#include<cstdio>
#include<cstring>
#define ll long long
#define MOD 19930726
using namespace std;
const int N=1e6+5;
ll k,sum[N];
int n,pal[N],len;
char s[N];
int min(int a,int b)
{
return a<b?a:b;
}
int max(int a,int b)
{
return a>b?a:b;
}
void manacher()
{
int mx=0,id;
for(int i=1;i<=len;i++){
if(mx>=i) pal[i]=min(mx-i+1,pal[2*id-i]);
else pal[i]=1;
while(s[i-pal[i]]==s[i+pal[i]]) pal[i]++;
if(pal[i]+i-1>mx) mx=i+pal[i]-1,id=i;
sum[0]++,sum[2*pal[i]]--;
}
}
ll pow(ll x,ll y)//x的y次方
{
ll base=x,ans=1;
for(ll i=y;i;i>>=1,base=(base*base)%MOD)
if(i&1) ans=(ans*base)%MOD;
return ans%MOD;
}
int main()
{
ll ans=1;
scanf("%d%lld",&n,&k);
scanf("%s",s+1);
len=strlen(s+1);
s[0]='+',s[++len]='-';
manacher();
for(int i=1;i<=n+1;i++) sum[i]+=sum[i-1];
for(int i=n;i>=1;i--){
if(i%2&&sum[i])
if(k-sum[i]>=1) ans=(ans*pow(i,sum[i]))%MOD,k-=sum[i];
else {
ans=(ans*pow(i,k))%MOD,k-=sum[i];k=0;break;
}
}
printf("%d",k?-1:ans);
return 0;
}