Untitled
unknown
plain_text
a year ago
5.6 kB
4
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