1 条题解

  • 0
    @ 2026-8-31 16:04:23

    我代码由我不由AI!!! 关于AI说我思路是错的但我最终AC这件事。

    事实上,我的思路的确不比标程简洁。

    解题思路

    处理回文,很自然地想到用双指针指一头一尾,然后往中间缩。姑且叫指前面的为 ii ,后面的为 jj

    对于 ii 索引来说,只要我当前选的字符的字典序小于 SiS_i 那么对于 iijj 中间的位置我可以随便选任何字母,字典序一定能比 SS 小。

    但是注意:当所选字母的字典序等于 SiS_i 时,接下来的选择就需要受字典序限制了。但是,这也等同于直接把 iji、j 去掉了,也就说不再需要考虑了。这比较像数位 dpdp

    因此,很自然地,贡献分成了两个部分:一个是没有顶到 SS 字典序的;反之则是顶到 SS 字典序的。

    对于第一种贡献:这十分好做。 iji、j 中间的 2626 个英文字母随便选即可,但是注意回文,所以说只有一半的位置随便选,还需注意奇偶,但是不麻烦。

    其中,最难的是中界处,即第二种贡献。第二种贡献需要在中界处计算,之所以叫中界处而不是中界点,就是因为中界处包含两种情况:奇、偶。当长度为奇数时,中间会剩下一个字符, i,ji, j 都会指在这里,偶数时中间会剩下两个字符, iji、j 分别指左、右。当然,你肯定想到了,贡献不就是 S[i] - 'A' + 1 吗?没错,但是需要做修正。

    因为,顶着 SS 的字典序时,SiS_i 可能 >Sj> S_j 这就意味着,最终不会满足字典序小。例如:AZAA,你会发现字母Z不能选,因为不可能是AZZA。所以,你的选择只会在 A ~ Y 间,你的答案需要--。但是不对,例如:BABA,按理来说,最左边的B大于了最右边的A,最终答案应该--,但是有这种情况:BAAB。这是因为中间的AB把字典序掰回来了,毕竟前面的字典序最先考虑,而最前面的B反而在回文的效果下更靠后考虑了。总的来说就是,字符越前,回文越后,字符靠后,回文靠前,最终字典序是看回文靠前的。注意,如果字典序相等,那么其实是不变的。当然,如果字典序又被掰回去的话,你的答案还是需要--的。

    (这道题我搞了一个上午+一个下午,头都痛了!讲也很抽象,还是看代码吧......)

    代码

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    int T = 1;
    const int N = 2e5 + 10;
    const int MOD = 998244353;
    int n;
    string s;
    
    //快速幂,帮助计算无限制时的中间26的某次方,一般来讲我是不喜欢用pow的
    int FastExp(int a, int b) {
    	if (b == 0) return 1;
    	int res = 1;
    	while (b) {
    		if (b & 1) {
    			res = (res * a) % MOD;
    		}
    		a = (a * a) % MOD;
    		b >>= 1;
    	}
    	return res;
    }
    
    void Solve() {
    	cin >> n >> s;
    	s = " " + s;
    	int ans = 0, sp = n % 2;//sp处理奇偶
    	bool flag = false;
    	for (int i = 1, j = n; i <= j; i++, j--) {
        //下面这个if判断是最难懂也是最重要的
    		if (s[i] > s[j]) flag = true;
    		else if (s[i] < s[j] && i != j) flag = false;
    		if (i == j || i == j - 1) {
    			if (s[i] >= s[j] && flag) ans--;
    			ans = (ans + s[i] - 'A' + 1) % MOD;
    		} else {
    			ans = (ans + (FastExp(26, (j - i - 1) / 2 + sp) * (s[i] - 'A')) % MOD) % MOD;
    		}
    	}
    	cout << ans << '\n';
    }
    
    signed main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	cin >> T;	
    	while (T--) {
    		Solve();
    	}
    	return 0;
    }
    

    信息

    ID
    2404
    时间
    2000ms
    内存
    1024MiB
    难度
    提高
    标签
    递交数
    4
    已通过
    1
    上传者