当前位置: 首页 > news >正文

P10816 [EC Final 2020] Namomo Subsequence|普及+

P10816 [EC Final 2020] Namomo Subsequence

题目描述

「gshfd1jkhaRaadfglkjerVcvuy0gf」教授 Pang 说道。

为了理解 Pang 教授的话,我们想要计算它的 namomo子序列\textit{namomo 子序列}namomo 子序列 的数量。Pang 教授的话是一个长度为 nnn 的字符串 sss,其中每个字符要么是英文字母(大小写),要么是数字。字符串 sss 的第 iii 个字符记为 s[i]s[i]s[i]1≤i≤n1\le i\le n1in)。字符串 sss 的子序列 ttt 由一组下标 t1,…,t6t_1, \ldots, t_6t1,,t6 定义,满足 1≤t1<t2<…<t6≤n1\le t_1 < t_2 < \ldots < t_6\le n1t1<t2<<t6n。定义一个函数 compare(c1,c2)compare(c_1, c_2)compare(c1,c2),对于两个字符 c1c_1c1c2c_2c2,当 c1=c2c_1=c_2c1=c2compare(c1,c2)=1compare(c_1, c_2)=1compare(c1,c2)=1,否则 compare(c1,c2)=0compare(c_1, c_2)=0compare(c1,c2)=0。当且仅当对于任意 1≤i<j≤61\le i<j\le 61i<j6compare(s[ti],s[tj])=compare(namomo[i],namomo[j])compare(s[t_i], s[t_j]) = compare(namomo[i], namomo[j])compare(s[ti],s[tj])=compare(namomo[i],namomo[j]) 时,ttt 是字符串 sss 的一个 namomo 子序列,其中 namomo[x]namomo[x]namomo[x] 表示字符串「namomo」的第 xxx 个字符(1≤x≤61\le x\le 61x6)。

输出给定字符串 sss 的 namomo 子序列的数量,结果对 998244353998244353998244353 取模。

输入格式

第一行包含一个长度为 nnn 的字符串 sss6≤n≤10000006\le n\le 10000006n1000000)。sss 仅包含小写英文字母(az)、大写英文字母(AZ)和数字(09)。

输出格式

输出一个整数,即答案对 998244353998244353998244353 取模。

输入输出样例 #1

输入 #1

wohaha

输出 #1

1

输入输出样例 #2

输入 #2

momomo

输出 #2

0

输入输出样例 #3

输入 #3

gshfd1jkhaRaadfglkjerVcvuy0gf

输出 #3

73

输入输出样例 #4

输入 #4

retiredMiFaFa0v0

输出 #4

33

说明/提示

(由 ChatGPT 4o 翻译)

前后缀分解

本题⟺\iff 形如abcdcd,a≠b≠c≠dabcdcd,a\neq b \neq c \neq dabcdcda=b=c=d的子序列。
将字符从小到大编码,即v1记录所有可能字符,排序。
code[v1[i]]=i。
v[i]=code[s[i]]
以下处理都针对v。
inxs[i]升序记录所有j,v[j]==iv[j]==iv[j]==i
一,i从大到1, 求cnt2[i],以v[i]开始的cd数量。如果v[i]≠cv[i]\neq cv[i]=c,为0。否则v[i+1…N-1]中d的数量。
二,i从大到1, 两层循环求cnt3[i],以v[i]开始的dcd数量。如果v[i]≠dv[i]\neq dv[i]=d,为0。否则∑(cnt2[i+1...N−1])\sum(cnt2[i+1...N-1])(cnt2[i+1...N1])
三,i从大到1, 两层循环求cnt4[i],以v[i]开始的cdcd数量。如果v[i]≠cv[i]\neq cv[i]=c,为0。否则∑(cnt3[i+1...N−1])\sum(cnt3[i+1...N-1])(cnt3[i+1...N1])
四,i从小到。
preCnt[i],记录v[i]是b的ab数量。
ans += ∑(preCnt[0...i−1])∗cnt4[i]\sum(preCnt[0...i-1]) * cnt4[i](preCnt[0...i1])cnt4[i]
时间复杂度O(n∑)O(n\sum)O(n)
任意inxs[i]都枚举∑×2次\sum \times 2次×2,作为c和d各被枚举∑\sum次。这样会超时。
preCnt 记录 i 之前非c非d数量。

代码

超时代码

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};template<long long MOD = 1000000007, class T1 = int, class T2 = long long>
class C1097Int
{
public:C1097Int(T1 iData = 0) :m_iData(iData% MOD){}C1097Int(T2 llData) :m_iData(llData% MOD) {}C1097Int  operator+(const C1097Int& o)const{return C1097Int(((T2)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((T2)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = ((T2)MOD + m_iData - o.m_iData) % MOD;return *this;}C1097Int  operator-(const C1097Int& o)const{return C1097Int(((T2)MOD + m_iData - o.m_iData) % MOD);}C1097Int  operator*(const C1097Int& o)const{return((T2)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((T2)m_iData * o.m_iData) % MOD;return *this;}C1097Int  operator/(const C1097Int& o)const{return *this * o.PowNegative1();}C1097Int& operator/=(const C1097Int& o){*this *= o.PowNegative1();return *this;}bool operator==(const C1097Int& o)const{return m_iData == o.m_iData;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(T2 n)const{C1097Int iRet = (T1)1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}T1 ToInt()const{return ((T2)m_iData + MOD) % MOD;}
private:T1 m_iData = 0;;
};typedef	C1097Int<998244353> BI;
class Solution {
public:Solution(const string& s) {vector<char> v;for (int i = 0; i < 26; i++) {v.emplace_back('a' + i);v.emplace_back('A' + i);}for (int i = 0; i < 10; i++) {v.emplace_back('0' + i);}int code[256] = { 0 };for (int i = 0; i < v.size(); i++) {code[v[i]] = i;}for (const auto& ch : s) {m_v.emplace_back(code[ch]);}m_iN = v.size();}int Ans() {BI ans;for (int c = 0; c < m_iN; c++) {for (int d = 0; d < m_iN; d++) {if (c == d) { continue; }ans += Do(c, d);}}return ans.ToInt();}BI Do(const int c, const int d)const {const int N = m_v.size();BI cnts1, cnts2, cnts3;vector<BI> cnt2(N), cnt3(N), cnt4(N);for (int i = N - 1; i >= 0; i--) {cnt2[i] = cnts1 * (c == m_v[i]);cnt3[i] = cnts2 * (d == m_v[i]);cnt4[i] = cnts3 * (c == m_v[i]);cnts1 += (d == m_v[i]);cnts2 += cnt2[i];cnts3 += cnt3[i];}auto preCnts = Pre(c, d);long long preCnt = 0;BI ans = 0;for (int i = 0; i < N; i++) {ans += cnt4[i] * preCnt;preCnt += preCnts[i];}return ans;};vector<long long> Pre(const int c, const int d) const {const int N = m_v.size();vector<int> cnt(m_iN);vector<long long> ans(N);long long cnts = 0;for (int i = 0; i < N; i++) {if ((c == m_v[i]) || (d == m_v[i])) { continue; }ans[i] = cnts - cnt[m_v[i]];cnts++;cnt[m_v[i]]++;}return ans;}vector<vector<int>> m_inxs;vector<int> m_v;int m_iN;
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;string s;cin >> s;
#ifdef _DEBUG	//printf("N=%d", N);//Out(lr, ",lr=");//Out(ps, ",ps=");//Out(ss, ",ss=");//Out(que, ",ope=");
#endif // DEBUG		auto res = Solution(s).Ans();cout << res << "\n";return 0;
}

卡常代码

卡第7各或9各样例,看了通过的乘积,第5个到最后一个用时相差不到10%。优化了近2小时搞不定。换简洁方法算了。

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
#include <chrono>
using namespace std::chrono;
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};template<long long MOD = 1000000007, class T1 = int, class T2 = long long>
class C1097Int
{
public:C1097Int(T1 iData = 0) :m_iData(iData% MOD){}C1097Int(T2 llData) :m_iData(llData% MOD) {}C1097Int  operator+(const C1097Int& o)const{return C1097Int(((T2)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((T2)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = ((T2)MOD + m_iData - o.m_iData) % MOD;return *this;}C1097Int  operator-(const C1097Int& o)const{return C1097Int(((T2)MOD + m_iData - o.m_iData) % MOD);}C1097Int  operator*(const C1097Int& o)const{return((T2)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((T2)m_iData * o.m_iData) % MOD;return *this;}C1097Int  operator/(const C1097Int& o)const{return *this * o.PowNegative1();}C1097Int& operator/=(const C1097Int& o){*this *= o.PowNegative1();return *this;}bool operator==(const C1097Int& o)const{return m_iData == o.m_iData;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(T2 n)const{C1097Int iRet = (T1)1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}T1 ToInt()const{return ((T2)m_iData + MOD) % MOD;}
private:T1 m_iData = 0;;
};typedef	C1097Int<998244353> BI;
class Solution {
public:const int MOD = 998244353;Solution(const string& s) {const int N = s.length();vector<char> v;for (int i = 0; i < 26; i++) {v.emplace_back('a' + i);v.emplace_back('A' + i);}for (int i = 0; i < 10; i++) {v.emplace_back('0' + i);}int code[256] = { 0 };for (int i = 0; i < v.size(); i++) {code[v[i]] = i;}m_v.resize(N);for (int i = 0; i < N; i++) {m_v[i] = code[s[i]];}m_iN = v.size();m_inxs.resize(m_iN, vector<int>(N));for (auto& v : m_inxs) {v.resize(0);}for (int i = 0; i < m_v.size(); i++) {m_inxs[m_v[i]].emplace_back(i);}m_preSqualSum.assign(m_iN, vector<long long>(N + 1));m_preSqualSums.assign(N + 1, 0);for (int i = 0; i < m_iN; i++) {for (int j = 0; j < m_inxs[i].size(); j++) {m_preSqualSum[i][m_inxs[i][j] + 1] = (long long)j * (j + 1) / 2;}}for (int i = 1; i <= N; i++) {for (int j = 0; j < m_iN; j++) {m_preSqualSum[j][i] = max(m_preSqualSum[j][i], m_preSqualSum[j][i - 1]);m_preSqualSums[i] += m_preSqualSum[j][i];}}cnt2.assign(N, 0); cnt3.assign(N, 0); cnt4.assign(N, 0);}int Ans() {BI ans;const int N = m_v.size();for (int c = 0; c < m_iN; c++) {for (int d = 0; d < m_iN; d++) {if (c == d) { continue; }ans += Do(c, d);}}return ans.ToInt();}BI Do(const int c, const int d) {const int N = m_v.size();long long cnts1 = (int)m_inxs[d].size();for (int i = 0, j = 0; i < m_inxs[c].size(); i++) {for (; (j < m_inxs[d].size()) && (m_inxs[d][j] <= m_inxs[c][i]); j++) {cnts1 -= 1;}cnt2[m_inxs[c][i]] = cnts1;}long long cnts2 = 0;for (const auto& i : m_inxs[c]) {cnts2 += cnt2[i];}cnts2 = cnts2 % MOD;for (int i = 0, j = 0; i < m_inxs[d].size(); i++) {for (; (j < m_inxs[c].size()) && (m_inxs[c][j] <= m_inxs[d][i]); j++) {cnts2 = (cnts2 - cnt2[m_inxs[c][j]]) % MOD;}cnt3[m_inxs[d][i]] = cnts2;}long long cnts3 = 0;for (const auto& i : m_inxs[d]) {cnts3 += cnt3[i];}cnts3 = cnts3 % MOD;for (int i = 0, j = 0; i < m_inxs[c].size(); i++) {for (; (j < m_inxs[d].size()) && (m_inxs[d][j] <= m_inxs[c][i]); j++) {cnts3 = (cnts3 - cnt3[m_inxs[d][j]]) % MOD;}cnt4[m_inxs[c][i]] = cnts3;}BI ans = 0;for (int i = 0, j = 0; i < m_inxs[c].size(); i++) {for (; (j < m_inxs[d].size()) && (m_inxs[d][j] < m_inxs[c][i]); j++);const int inx = m_inxs[c][i];long long preCnt = inx - i - j;preCnt = preCnt * (preCnt - 1) / 2 - (m_preSqualSums[inx] - m_preSqualSum[c][inx] - m_preSqualSum[d][inx]);ans += BI(preCnt) * cnt4[inx];}for (const int i : m_inxs[c]) {cnt2[i] = cnt4[i] = 0;}for (const auto& i : m_inxs[d]) {cnt3[i] = 0;}return ans;};vector<vector<int>> m_inxs;vector<int> m_v;int m_iN;vector<vector<long long>> m_preSqualSum;vector<long long> m_preSqualSums;vector<long long> cnt2, cnt3, cnt4;
};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;string s;cin >> s;
#ifdef _DEBUG	//printf("N=%d", N);//Out(lr, ",lr=");//Out(ps, ",ps=");//Out(ss, ",ss=");//Out(que, ",ope=");
#endif // DEBUG		auto res = Solution(s).Ans();cout << res << "\n";return 0;
}

重新写了简洁版也卡常

忙了一天没过,挫折感十分的强烈。

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
#include <chrono>
using namespace std::chrono;
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};template<long long MOD = 1000000007, class T1 = int, class T2 = long long>
class C1097Int
{
public:C1097Int(T1 iData = 0) :m_iData(iData% MOD){}C1097Int(T2 llData) :m_iData(llData% MOD) {}C1097Int  operator+(const C1097Int& o)const{return C1097Int(((T2)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((T2)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = ((T2)MOD + m_iData - o.m_iData) % MOD;return *this;}C1097Int  operator-(const C1097Int& o)const{return C1097Int(((T2)MOD + m_iData - o.m_iData) % MOD);}C1097Int  operator*(const C1097Int& o)const{return((T2)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((T2)m_iData * o.m_iData) % MOD;return *this;}C1097Int  operator/(const C1097Int& o)const{return *this * o.PowNegative1();}C1097Int& operator/=(const C1097Int& o){*this *= o.PowNegative1();return *this;}bool operator==(const C1097Int& o)const{return m_iData == o.m_iData;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(T2 n)const{C1097Int iRet = (T1)1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}T1 ToInt()const{return ((T2)m_iData + MOD) % MOD;}
private:T1 m_iData = 0;;
};typedef	C1097Int<998244353> BI;typedef	C1097Int<998244353> BI;class Solution {public:	Solution(const string& s) {	const int N = s.length();vector<char> v;for (int i = 0; i < 26; i++) {v.emplace_back('a' + i);		}for (int i = 0; i < 26; i++) {v.emplace_back('A' + i);}for (int i = 0; i < 10; i++) {v.emplace_back('0' + i);}int code[256] = { 0 };for (int i = 0; i < v.size(); i++) {code[v[i]] = i;}m_v.resize(N);for (int i = 0; i < N;i++) {m_v[i] = code[s[i]];}				m_iN = v.size();	m_cnt.assign(m_iN,0);cnt2.assign(m_iN, vector<BI>(m_iN)); cnt3.assign(m_iN, vector<BI>(m_iN)); m_preSqualSum.assign(m_iN, vector<long long>(N + 1));m_preSqualSums.assign(N + 1, 0);m_preCnt.assign(m_iN, vector<int>(N + 1));vector<int> cnt(m_iN);for (int i = 0; i < N; i++) {cnt[m_v[i]]++;m_preSqualSum[m_v[i]][i+ 1] = cnt[m_v[i]] * (cnt[m_v[i]] - 1) / 2;}for (int i = 1; i <= N; i++) {for (int j = 0; j < m_iN; j++) {m_preSqualSum[j][i] = max(m_preSqualSum[j][i], m_preSqualSum[j][i - 1]);m_preSqualSums[i] += m_preSqualSum[j][i];m_preCnt[j][i] = m_preCnt[j][i - 1] + (j == m_v[i - 1]);}}}int Ans() {				BI ans;const int N = m_v.size();				for (int i = N - 1; i >= 0; i--) {					for (int j = 0; j < m_iN; j++) {if (m_v[i] == j) { continue; }cnt2[m_v[i]][j] += m_cnt[j];cnt3[m_v[i]][j] += cnt2[j][m_v[i]];//cnt4[m_v[i]][j] += cnt3[j][m_v[i]];BI preCnt =BI(i)- m_preCnt[j][i]- m_preCnt[m_v[i]][i];preCnt = preCnt * (preCnt - 1) / 2 - (m_preSqualSums[i] - m_preSqualSum[m_v[i]][i] - m_preSqualSum[j][i]);ans += BI(preCnt) * cnt3[j][m_v[i]];}m_cnt[m_v[i]]+=1;}return ans.ToInt();}	vector<int> m_v;int m_iN;	vector<vector<BI>> cnt2, cnt3;vector<BI> m_cnt;vector<vector<long long>> m_preSqualSum;vector<long long> m_preSqualSums;vector<vector<int>> m_preCnt;};int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;string s;cin >> s;
#ifdef _DEBUG	//printf("N=%d", N);//Out(lr, ",lr=");//Out(ps, ",ps=");//Out(ss, ",ss=");//Out(que, ",ope=");
#endif // DEBUG		auto res = Solution(s).Ans();cout << res << "\n";return 0;
}

放弃了

BI改成long long或int。
加法后,直接也不行。

void DoMod(int& x) {				if (x > MOD) { x -= MOD; }}

单元测试

TEST_METHOD(TestMethod11){auto res = Solution("abcdcd").Ans();AssertEx(1, res);}TEST_METHOD(TestMethod12){auto res = Solution("adbcdcd").Ans();AssertEx(1, res);}TEST_METHOD(TestMethod13){auto res = Solution("gshfd1jkhaRaadfglkjerVcvuy0gf").Ans();AssertEx(73, res);}TEST_METHOD(TestMethod14){auto res = Solution("retiredMiFaFa0v0").Ans();AssertEx(33, res);}TEST_METHOD(TestMethod15){auto res = Solution("aabcdcd").Ans();AssertEx(2, res);}TEST_METHOD(TestMethod16){auto res = Solution("aabddd2Aczdcdzd").Ans();AssertEx(88, res);}TEST_METHOD(TestMethod17){auto res = Solution("aabxx3d32zdddddddxxx3d32ddaxxx3d322bdesxxdddxx3d32sdddddxxxxd3xxxd32222467890xxxd322d2AczfAABBBCDDxxxd322DDDDDxxxd3xxxd32222DDDfffdcsdddzd").Ans();AssertEx(23578825, res);}TEST_METHOD(TestMethod18){auto res = Solution("abcddcd").Ans();AssertEx(2, res);}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

http://www.dtcms.com/a/311997.html

相关文章:

  • 堆----1.数组中的第K个最大元素
  • [buuctf-misc]喵喵喵
  • Linux学习--数据结构
  • 前端-移动Web-day3
  • 基于springboot的郑州旅游景点推荐系统
  • Kotlin单例模式懒汉模式:LazyThreadSafetyMode.SYNCHRONIZED(2)
  • 多线程(二) ~ 线程核心属性与状态
  • C#中对于List的多种排序方式
  • LeeCode 88. 合并两个有序数组
  • DeepSpeed - 超大LLM分布式训练框架 ZeRO技术
  • Python day32
  • 力扣 二叉树遍历 中序/前序/后序(递归和迭代版)
  • dbt中多源数据的处理
  • 混合嵌入与置信度增强:新一代RAG技术如何提升LLM性能
  • 1.6 vue 监听
  • JavaScript 原始值与引用值
  • SQL语言学习(group by,having)
  • PyTorch 中 Tensor 统计学函数及相关概念
  • 基于单片机一氧化碳CO检测/煤气防中毒检测报警系统
  • OneCode 3.0智能分页拦截器深度解析:从拦截机制到性能优化
  • 轨道追逃博弈仿真
  • 输电线路建模与电力负荷特性详解(含等值模型与曲线分析)
  • Vue 详情模块 4
  • SQL语言学习(JOIN)
  • Orange的运维学习日记--25.Linux文件系统基本管理
  • 使用xshell连接远程腾讯云服务器,报错:Xshell Socket error Event: 32 Error: 10053
  • 智能图书馆管理系统开发实战系列(五):前后端集成 - koffi调用与接口设计
  • 用resmon搜索某文件被未知程序占用而无法删除
  • 第15届蓝桥杯Python青少组_省赛_中/高级组2024年8月真题
  • Java,八股,cv,算法——双非研0四修之路day23