样例过了,但是0分,在线求助
查看原帖
样例过了,但是0分,在线求助
970620
Cure_scenery楼主2023/7/28 09:40
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxx=11000010;//定义字符数最大长度
const int mod=19939726;//定义模数

char b[maxx],a[maxx<<1];//定义原始字符串和处理后的字符串
//hw每个字符的最长回文半径,ans最终结果,c记录各个长度的回文串的个数
int hw[maxx<<1],ans=1,n,c[maxx];
ll now,m;//当前的和谐小群体个数,要找的和谐小群体个数

// 快速幂计算 a^k % MOD
int fast_pow(int a, ll k){
	int ans = 1;
	while(k){
		if(k & 1) ans = (ll)ans * a % mod;  // 如果k为奇数,累乘到结果中
		a = (ll) a * a % mod;  // 计算a的平方取模
		k >>= 1;  // k右移一位,相当于除以2
	}
	return ans;
}

int main(){
	// 读入n和m
	scanf("%d%lld", &n, &m);
	// 读入原始字符串b
	scanf("%s", b);
	// 使用Manacher算法的预处理,插入'#'使得回文串长度一定为奇数
	a[0] = a[1] = '#';
	for(int i = 0; i < n; ++i)
		a[(i << 1) + 2] = b[i], a[(i << 1) + 3] = '#';
	// 使用Manacher算法找出所有回文串
	int maxright = 0, mid; n = (n << 1) + 3;
	for(int i = 1; i < n; ++i){
		if(i < maxright)
			hw[i] = min(hw[(mid << 1) - i], hw[mid] + mid - i);
		else hw[i] = 1;
		while(a[i + hw[i]] == a[i - hw[i]]) ++hw[i];
		if(hw[i] + i > maxright){
			maxright = hw[i] + i;
			mid = i;
		}
		// 统计各个长度的回文串个数
		++c[hw[i] - 1];
	}
	// 从大到小遍历所有的回文串长度,计算结果
	for(int i = (n - 3) >> 1; i; --i){
		// 如果回文串长度为偶数,跳过
		if(i & 1 ^ 1) continue;
		// 累加当前长度的回文串个数
		now += c[i];
		// 如果当前的和谐小群体个数大于等于需要的数量,计算结果并结束
		if(m <= now){ ans = (ll) ans * fast_pow(i, m) % mod; m = 0; break; }
		// 如果当前的和谐小群体个数小于需要的数量,计算结果并更新需要的数量
		m -= now; ans = (ll) ans * fast_pow(i, now) % mod;
	}
	// 如果还有需要的和谐小群体没有找到,输出-1
	if(m) ans = -1;
	printf("%d\n", ans);
	return 0;
}
2023/7/28 09:40
加载中...