結果
| 問題 |
No.1195 数え上げを愛したい(文字列編)
|
| コンテスト | |
| ユーザー |
Nachia
|
| 提出日時 | 2020-11-17 16:15:00 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 492 ms / 3,000 ms |
| コード長 | 3,559 bytes |
| コンパイル時間 | 2,183 ms |
| コンパイル使用メモリ | 183,196 KB |
| 実行使用メモリ | 34,560 KB |
| 最終ジャッジ日時 | 2024-07-23 08:21:28 |
| 合計ジャッジ時間 | 10,969 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 26 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
#define rep(i,n) for(int i=0; i<(n); i++)
template<ULL M>
struct static_modint {
ULL x;
static_modint(ULL val = 0) : x(val) {}
template<class intTy, enable_if_t<is_integral<intTy>::value&& is_unsigned<intTy>::value, void*> isUnsignedInt = nullptr>
static static_modint mod_construct(intTy val) { return static_modint(val % M); }
template<class intTy, enable_if_t<is_integral<intTy>::value&& is_signed<intTy>::value, void*> isSignedInt = nullptr>
static static_modint mod_construct(intTy val) { LL buf = val % (LL)M; if (buf < 0) buf += M; return static_modint((ULL)buf); }
static_modint operator-() const { if (x == 0) return 0; else return M - x; }
static_modint& operator+=(static_modint r) { x += r.x; if (x >= M) x -= M; return *this; }
static_modint operator+(static_modint r) const { static_modint res = x; return res += r; }
static_modint& operator-=(static_modint r) { x += M - r.x; if (x >= M) x -= M; return *this; }
static_modint operator-(static_modint r) const { static_modint res = x; return res -= r; }
static_modint& operator*=(static_modint r) { x = x * r.x % M; return *this; }
static_modint operator*(static_modint r) const { return static_modint(x * r.x % M); }
static_modint pow(ULL r) const {
if (r == 0) return static_modint(1);
static_modint res = pow(r / 2);
res *= res;
if (r % 2) res *= *this;
return res;
}
static_modint inv() const { return pow(M - 2); }
static_modint& operator/=(static_modint r) { *this *= r.inv(); return *this; }
static_modint operator/(static_modint r) const { return *this * r.inv(); }
ULL& operator*() { return x; }
const ULL& operator*() const { return x; }
bool operator==(static_modint r) const { return x == *r; }
bool operator!=(static_modint r) const { return x != *r; }
};
const ULL M = 998244353;
using MLL = static_modint<M>;
void NTT(vector<MLL>& A,MLL g){
int N=A.size();
for(int i=0,j=0; j<N; j++){
if(i<j) swap(A[i],A[j]);
for(int k=N>>1; k>(i^=k); k>>=1);
}
for(int i=1; i<N; i<<=1){
MLL q=g.pow((M-1)/i/2), qj=1;
rep(j,i){
for(int k=j; k<N; k+=i*2){
MLL l=A[k],r=A[k+i]*qj;
A[k]=(l+r);
A[k+i]=(l+M-r);
}
qj*=q;
}
}
}
struct Fuse{ ULL M,G; };
vector<MLL> convolution(const vector<MLL>& A,const vector<MLL>& B) {
const MLL g=3;
int Z=1; while(Z<A.size()+B.size()) Z<<=1;
vector<MLL> Ax(Z),Bx(Z);
MLL iZ=MLL(Z).inv();
rep(i,Z) Ax[i]=Bx[i]=0;
rep(i,A.size()) Ax[i]=A[i];
rep(i,B.size()) Bx[i]=B[i];
NTT(Ax,g);
NTT(Bx,g);
rep(i,Z) Ax[i]=Ax[i]*Bx[i];
NTT(Ax,g.inv());
rep(i,Z) Ax[i]=Ax[i]*iZ;
Ax.resize(A.size()+B.size()-1);
return move(Ax);
}
const int Z = 300000;
MLL F[Z+1], I[Z+1], iF[Z+1];
vector<MLL> A[26];
int main() {
rep(i,26) A[i] = {1};
{
string S; cin>>S;
for(int c:S) A[c-'a'].push_back(1);
}
F[0]=I[1]=iF[0]=1;
for(int i=1; i<=Z; i++) F[i]=F[i-1]*i;
for(int i=2; i<=Z; i++) I[i]=-MLL(M/i)*I[M%i];
for(int i=1; i<=Z; i++) iF[i]=iF[i-1]*I[i];
rep(c,26) rep(i,A[c].size()) A[c][i] *= iF[i];
priority_queue<pair<int,int>> Q;
rep(i,26) Q.push({ -(int)A[i].size(), i });
while(Q.size()>=2){
int p1=Q.top().second; Q.pop();
int p2=Q.top().second; Q.pop();
A[p1]=convolution(A[p1],A[p2]);
Q.push({-(int)A[p1].size(),p1});
}
int p=Q.top().second; Q.pop();
rep(i,A[p].size()) A[p][i] *= F[i];
MLL ans = 0;
for(int i=1; i<A[p].size(); i++) ans += A[p][i];
cout<<*ans<<endl;
return 0;
}
Nachia