@ljt12138
2017-03-18T16:08:31.000000Z
字数 3464
阅读 981
解题报告
计算:
正好看到《具体数学》上处理和式的Tricks,虽然热身题也不会做,但碾OI题还是很稳的(Orz神犇高教授)...
对于:
将b数组倒置,即
化简得到
我们想得到形如
的形式。只需要将后式中的
条件是
所以
然后用卷积做就好了。
#include <bits/stdc++.h>using namespace std;typedef complex<double> Complex;const int MAXN = 300005;int rev[MAXN];Complex A[MAXN];Complex a[MAXN], b[MAXN], c[MAXN];int n;void fft(Complex a[], int n, int flag){int lgn = int(log2(n)+0.01);rev[0] = 0;for (int i = 1; i < n; i++)rev[i] = (rev[i>>1]>>1)|((i&1)<<(lgn-1));for (int i = 0; i < n; i++)A[rev[i]] = a[i];Complex u, t;for (int k = 2; k <= n; k <<= 1) {Complex dw = Complex(cos(2*M_PI/k), flag*sin(2*M_PI/k));for (int i = 0; i < n; i += k) {Complex w = 1;for (int j = 0; j < k>>1; j++) {u = A[i+j], t = w*A[i+j+(k>>1)];A[i+j] = u+t, A[i+j+(k>>1)] = u-t;w *= dw;}}}for (int i = 0; i < n; i++)a[i] = A[i]/Complex(flag==1?1:n,0);}int main(){scanf("%d", &n);for (int i = 0; i < n; i++) {double x, y; scanf("%lf%lf", &x, &y);a[i] = Complex(x, 0), b[n-i-1] = Complex(y, 0);}int nn = 1;while (nn < n*2) nn <<= 1;fft(a, nn, 1), fft(b, nn, 1);for (int i = 0; i < nn; i++) c[i] = a[i]*b[i];fft(c, nn, -1);for (int i = 0; i < n; i++) printf("%d\n", int(c[i+n-1].real()+0.01));return 0;}
给定一个ab串,求所有不连续回文子序列的数量和。
由于卷积可以处理关于一个对称轴两侧对称的字符总数,因此将串中的a、b变为0、1,自己和自己做卷积,就可以求出所有对称轴下b所对应数对称的字符总数。然后把a、b变为1、0,求出a的结果,相加即为关于对称轴两边对称的总字符数
那么如何去除连续的呢?跑一遍Manacher就好了。复杂度
#include <bits/stdc++.h>using namespace std;const int MAXN = 300005;typedef complex<double> Complex;int rev[MAXN];Complex A[MAXN];const long long mod = 1000000007ll;void fft(Complex a[], int n, int flag){rev[0] = 0;int lgn = int(log2(n)+0.01);for (int i = 1; i < n; i++)rev[i] = (rev[i>>1]>>1)|((i&1)<<(lgn-1));for (int i = 0; i < n; i++)A[rev[i]] = a[i];Complex u, t;for (int k = 2; k <= n; k <<= 1) {Complex dw = Complex(cos(2*M_PI/k), sin(flag*2*M_PI/k));for (int i = 0; i < n; i += k) {Complex w = 1;for (int j = 0; j < k>>1; j++) {u = A[i+j], t = A[i+j+(k>>1)]*w;A[i+j] = u+t, A[i+j+(k>>1)] = u-t;w *= dw;}}}for (int i = 0; i < n; i++)a[i] = A[i]/(flag == 1?1:Complex(n,0));}int p[MAXN];long long manacher(char str[], int n){str[0] = '^', str[++n] = '#';int id = 0, mx = 0;long long ans = 0;for (int i = 1; i <= n; i++) {if (mx >= i) p[i] = min(mx-i, p[id-(i-id)]);else p[i] = 0;while (str[i+p[i]+1] == str[i-p[i]-1]) p[i]++;if (i+p[i] > mx) id = i, mx = i+p[i];(ans += p[i]+1) %= mod;}ans--;id = mx = 0;for (int i = 1; i < n; i++) {if (mx >= i) p[i] = min(mx-i, p[id-(i-id)]);else p[i] = 0;while (str[i+p[i]+1] == str[i-p[i]]) p[i]++;if (i+p[i] > mx) id = i, mx = i+p[i];(ans += p[i]) %= mod;}return ans;}long long power(int a, int n){if (n == 0) return 1;long long p = power(a, n>>1);(p *= p) %= mod;if (n&1) (p *= a) %= mod;return p;}char str[MAXN];Complex a[MAXN], c[MAXN];int cp[MAXN];int main(){scanf("%s", str+1);int len = strlen(str+1), n;for (n = 1; n < (len+1)*2; n<<=1);long long sub = manacher(str, len), ans = 0;for (int i = 1; i <= len; i++) a[i] = str[i] == 'a';fft(a, n, 1);for (int i = 0; i < n; i++) a[i] *= a[i];fft(a, n, -1);for (int i = 0; i < n; i++) cp[i] = int(a[i].real()+0.1), a[i] = 0;for (int i = 1; i <= len; i++) a[i] = str[i] == 'b';fft(a, n, 1);for (int i = 0; i < n; i++) a[i] *= a[i];fft(a, n, -1);for (int i = 0; i < n; i++) cp[i] += int(a[i].real()+0.1);for (int i = 0; i < n; i++) (ans += power(2, (cp[i]+1)/2)-1) %= mod;cout << ((ans-sub)%mod+mod)%mod << endl;return 0;}