結果
| 問題 |
No.1195 数え上げを愛したい(文字列編)
|
| コンテスト | |
| ユーザー |
沙耶花
|
| 提出日時 | 2020-08-22 17:29:23 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 576 ms / 3,000 ms |
| コード長 | 3,063 bytes |
| コンパイル時間 | 3,093 ms |
| コンパイル使用メモリ | 209,352 KB |
| 最終ジャッジ日時 | 2025-01-13 10:39:00 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 26 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define modulo 998244353
#define mod(mod_x) ((((long long)mod_x+modulo))%modulo)
#define Inf 1000000005
int beki(long long a,long long b,int M = modulo){
int x = 1;
while(b!=0){
if(b&1){
x=((long long)x*a)%M;
}
a=((long long)a*a)%M;
b>>=1;
}
return x;
}
int gyakugen(int a){
return beki(a,modulo-2);
}
struct combi{
deque<int> kaijou;
deque<int> kaijou_;
combi(int n){
kaijou.push_back(1);
for(int i=1;i<=n;i++){
kaijou.push_back(mod(kaijou[i-1]*i));
}
int b=gyakugen(kaijou[n]);
kaijou_.push_front(b);
for(int i=1;i<=n;i++){
int k=n+1-i;
kaijou_.push_front(mod(kaijou_[0]*k));
}
}
int combination(int n,int r){
if(r>n)return 0;
int a = mod(kaijou[n]*kaijou_[r]);
a=mod(a*kaijou_[n-r]);
return a;
}
int junretsu(int a,int b){
int x = mod(kaijou_[a]*kaijou_[b]);
x=mod(x*kaijou[a+b]);
return x;
}
int catalan(int n){
return mod(combination(2*n,n)*gyakugen(n+1));
}
};
void NTT(vector<int> &A){
int n = A.size();
vector<int> tmp(n,0);
int mask = n-1;
for(int i=n>>1;i>=1;i>>=1){
int r = (modulo-1)/n;
r *= i;
int w = beki(3,r);
int now = 1;
for(int j=0;j<n;j+=i){
for(int k=0;k<i;k++){
tmp[j+k] = mod(A[((j<<1)&mask)|k] + mod(now*A[(((j << 1)|i)&mask)|k]));
}
now = mod(now * w);
}
swap(A,tmp);
}
int num;
for(int i=0;true;i++){
if((n>>i)&1){
num = i;
break;
}
}
if(num&1){
swap(A,tmp);
for(int i=0;i<n;i++)A[i] = tmp[i];
}
return;
}
vector<int> do_NTT(vector<int> A,vector<int> B){
int n = A.size()+B.size()-1;
if(min(A.size(),B.size())<=150){
vector<int> ret(n,0);
for(int i=0;i<A.size();i++){
for(int j=0;j<B.size();j++){
ret[i+j] = mod(ret[i+j] + mod(A[i]*B[j]));
}
}
return ret;
}
for(int i=0;true;i++){
if((1<<i)>=n){
n = (1<<i);
break;
}
}
A.resize(n),B.resize(n);
bool f = A==B;
NTT(A);
if(f)B=A;
else NTT(B);
int rev = gyakugen(n);
vector<int> c(n);
for(int i=0;i<n;i++)c[i] = mod(mod(A[i]*B[i])*rev);
reverse(c.begin()+1,c.end());
NTT(c);
return c;
}
int main(){
vector<int> cnt(26,0);
string S;
cin>>S;
for(int i=0;i<S.size();i++){
cnt[S[i]-'a']++;
}
combi C(1000000);
vector<vector<int>> now;
for(int i=0;i<26;i++){
if(cnt[i]==0)continue;
vector<int> x(cnt[i]+1,1);
now.push_back(x);
}
while(now.size()!=1){
vector<vector<int>> New;
for(int i=0;i<now.size();i+=2){
if(i+1==now.size()){
New.push_back(now[i]);
break;
}
for(int j=0;j<now[i].size();j++){
now[i][j] = mod(now[i][j] * C.kaijou_[j]);
}
for(int j=0;j<now[i+1].size();j++){
now[i+1][j] = mod(now[i+1][j] * C.kaijou_[j]);
}
vector<int> X = do_NTT(now[i],now[i+1]);
for(int j=0;j<X.size();j++){
X[j] = mod(X[j] * C.kaijou[j]);
}
while(X.size()>0&&X.back()==0)X.pop_back();
New.push_back(X);
}
swap(now,New);
}
int ans =0;
for(int i=1;i<now[0].size();i++){
ans = mod(ans + now[0][i]);
}
cout<<ans<<endl;
return 0;
}
沙耶花