Untitled
unknown
plain_text
a year ago
5.6 kB
7
Indexable
#include<bits/stdc++.h>
#define ll long long
#define pp push_back
#define endl '\n'
#define all(x) x.begin(),x.end()
#define ld long double
#define PI acos(-1)
#define sin(a) sin((a)*PI/180)
#define cos(a) cos((a)*PI/180)
#define ones(x) __builtin_popcountll(x)
//#define int ll
using namespace std;
void Drakon() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef Clion
freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#endif
}
unsigned long long inf = 1e10;
const double EPS = 1e-6;
const int MOD = 1000000007, N = 200005, LOG = 25;
ll mul(const ll &a, const ll &b) {
return (a % MOD + MOD) * (b % MOD + MOD) % MOD;
}
ll add(const ll &a, const ll &b) {
return (a + b + 2 * MOD) % MOD;
}
int pw(ll x, ll y) {
ll ret = 1;
while (y > 0) {
if (y % 2 == 0) {
x = mul(x, x);
y = y / 2;
} else {
ret = mul(ret, x);
y = y - 1;
}
}
return ret;
}
#define vi vector<int>
#define rep(aa, bb, cc) for(int aa = bb; aa < cc;aa++)
#define sz(a) (int)a.size()
typedef complex<double> C;
typedef vector<double> vd;
void fft(vector<C>& a) {
int n = sz(a), L = 31 - __builtin_clz(n);
static vector<complex<long double>> R(2, 1);
static vector<C> rt(2, 1); // (^ 10% faster if double)
for (static int k = 2; k < n; k *= 2) {
R.resize(n); rt.resize(n);
auto x = polar(1.0L, acos(-1.0L) / k);
rep(i,k,2*k) rt[i] = R[i] = i&1 ? R[i/2] * x : R[i/2];
}
vi rev(n);
rep(i,0,n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2;
rep(i,0,n) if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int k = 1; k < n; k *= 2)
for (int i = 0; i < n; i += 2 * k) rep(j,0,k) {
// C z = rt[j+k] * a[i+j+k]; // (25% faster if hand-rolled) /// include-line
auto x = (double *)&rt[j+k], y = (double *)&a[i+j+k]; /// exclude-line
C z(x[0]*y[0] - x[1]*y[1], x[0]*y[1] + x[1]*y[0]); /// exclude-line
a[i + j + k] = a[i + j] - z;
a[i + j] += z;
}
}
template<int M> vi convMod(const vi &a, const vi &b) {
if (a.empty() || b.empty()) return {};
vi res(sz(a) + sz(b) - 1);
int B=32-__builtin_clz(sz(res)), n=1<<B, cut=int(sqrt(M));
vector<C> L(n), R(n), outs(n), outl(n);
rep(i,0,sz(a)) L[i] = C((int)a[i] / cut, (int)a[i] % cut);
rep(i,0,sz(b)) R[i] = C((int)b[i] / cut, (int)b[i] % cut);
fft(L), fft(R);
rep(i,0,n) {
int j = -i & (n - 1);
outl[j] = (L[i] + conj(L[j])) * R[i] / (2.0 * n);
outs[j] = (L[i] - conj(L[j])) * R[i] / (2.0 * n) / 1i;
}
fft(outl), fft(outs);
rep(i,0,sz(res)) {
ll av = (ll)(real(outl[i])+.5), cv = (ll)(imag(outs[i])+.5);
ll bv = (ll)(imag(outl[i])+.5) + (ll)(real(outs[i])+.5);
res[i] = ((av % M * cut + bv) % M * cut + cv) % M;
}
return res;
}
const int P1 = 31, P2 = 37;
int pw1[N], pw2[N], inv1[N], inv2[N];
void pre() {
pw1[0] = inv1[0] = pw2[0] = inv2[0] = 1;
int mulInv1 = pw(P1, MOD - 2);
int mulInv2 = pw(P2, MOD - 2);
for (int i = 1; i < N; i++) {
pw1[i] = mul(pw1[i - 1], P1);
pw2[i] = mul(pw2[i - 1], P2);
inv1[i] = mul(inv1[i - 1], mulInv1);
inv2[i] = mul(inv2[i - 1], mulInv2);
}
}
void solve() {
string s;
cin >> s;
map<pair<int, int>, int> freq;
pair<int, int> pre = {0, 0}, suf = {0, 0};
for (int i = 0; i < s.size(); ++i) {
suf.first = add(suf.first, mul(s[i] - 'a' + 1, pw1[i]));
suf.second = add(suf.second, mul(s[i] - 'a' + 1, pw2[i]));
}
for (int i = 0; i <= s.size(); ++i) {
for (int j = 1; j <= 26; ++j) {
pair<int, int> cur = pre;
cur.first = add(cur.first, mul(j, pw1[i]));
cur.second = add(cur.second, mul(j, pw2[i]));
cur.first = add(cur.first, mul(suf.first, pw1[i + 1]));
cur.second = add(cur.second, mul(suf.second, pw2[i + 1]));
freq[cur] ++;
}
if(i == s.size())break;
suf.first = add(suf.first, -(s[i] - 'a' + 1));
suf.second = add(suf.second, -(s[i] - 'a' + 1));
suf.first = mul(suf.first, inv1[1]);
suf.second = mul(suf.second, inv1[1]);
pre.first = add(pre.first, mul(s[i] - 'a' + 1, pw1[i]));
pre.second = add(pre.second, mul(s[i] - 'a' + 1, pw2[i]));
}
vector<vi> poly;
for(auto &f : freq) {
int prob = mul(pw(s.size() + 1, MOD - 2), pw(26, MOD - 2));
prob = mul(prob, f.second);
poly.push_back({1, prob});
}
poly = {{1, pw(6, MOD - 2)}, {1, pw(2, MOD - 2)}, {1, pw(3, MOD - 2)}};
while (poly.size() > 1) {
vector<vi> res;
for (int i = 0; i + 1 < poly.size(); i += 2) {
res.push_back(convMod<MOD>(poly[i], poly[i + 1]));
}
if(poly.size() & 1)res.push_back(poly.back());
swap(poly, res);
}
vector<int> p = poly[0];
int fac[p.size()];
fac[0] = 1;
for (int i = 1; i < p.size(); ++i) {
fac[i] = mul(fac[i - 1], i);
}
int ans = 1;
for (int i = 1; i < p.size(); ++i) {
ans = add(ans, mul(p[i], fac[i]));
}
cout << ans;
}
signed main() {
Drakon();
pre();
int t = 1;
//cin >> t;
while (t--) {
solve();
}
}Editor is loading...
Leave a Comment