版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82798820
Description
给你一个只有01和?的字符串,问你是否存在一种把?改成01的方案使串存在一个长度为1−n的border。
Sample Input
1?0?
Sample Output
17
被gay队D飞的题。。。
这题肉老大看了一眼说是FFT%%%
式子就会化成:
当这个点为?时,t[i]=0,那么式子得出来就会是0,如果两个数相同,式子得出来也会是0,然后就变成FFT然后判结果是不是0即可。
但有一点就是两个相同的?,可能会有不同的值。。。
然后就%gay。。。
因为你对于长度为k的匹配串,那么第i个位置会跟i+len-k匹配那么其实i+len-k又会跟,i+len-k+len-k匹配,那你就这样跳着判一下即可,时间复杂度可用调和级数证明。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const double PI = acos(-1.0);
struct Complex {
double r, i;
Complex() {r = i = 0;}
Complex(double _r, double _i) {r = _r, i = _i;}
friend Complex operator + (Complex a, Complex b) {return Complex(a.r + b.r, a.i + b.i);}
friend Complex operator - (Complex a, Complex b) {return Complex(a.r - b.r, a.i - b.i);}
friend Complex operator * (Complex a, Complex b) {return Complex(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r);}
} A[2100000], B[2100000];
int u1[2100000], u2[2100000], u3[2100000];
int R[2100000], a[510000];
char ss[510000];
void fft(Complex *yy, int len, int o) {
for(int i = 0; i < len; i++) if(i < R[i]) swap(yy[i], yy[R[i]]);
for(int i = 1; i < len; i *= 2) {
Complex wn(cos(PI / i), sin(o * PI / i));
for(int j = 0; j < len; j += i * 2) {
Complex w(1, 0);
for(int k = 0; k < i; k++, w = w * wn) {
Complex u = yy[j + k];
Complex v = yy[j + k + i] * w;
yy[j + k] = u + v;
yy[j + k + i] = u - v;
}
}
} if(o == -1) for(int i = 0; i < len; i++) yy[i].r /= len;
}
int main() {
scanf("%s", ss + 1);
int n = strlen(ss + 1), nn = n;
for(int i = 1; i <= n; i++) {
if(ss[i] == '?') a[i] = 0;
else a[i] = ss[i] - '0' + 1;
}
int m = n;
for(int i = 0; i < n; i++) A[i].r = a[i + 1] * a[i + 1];
for(int i = n - 1; i >= 0; i--) B[i].r = a[n - i] * a[n - i];
m *= 2; int l = 0;
for(n = 1; n <= m; n *= 2) l++;
for(int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | (i & 1) << (l - 1);
fft(A, n, 1), fft(B, n, 1);
for(int i = 0; i < n; i++) A[i] = A[i] * B[i];
fft(A, n, -1);
for(int i = 1; i <= n; i++) u1[i] = int(A[i - 1].r + 0.5);
for(int i = 0; i < n; i++) A[i] = B[i] = Complex(0, 0);
for(int i = 0; i < nn; i++) A[i].r = a[i + 1] * a[i + 1] * a[i + 1];
for(int i = nn - 1; i >= 0; i--) B[i].r = a[nn - i];
fft(A, n, 1), fft(B, n, 1);
for(int i = 0; i < n; i++) A[i] = A[i] * B[i];
fft(A, n, -1);
for(int i = 1; i <= n; i++) u2[i] = int(A[i - 1].r + 0.5);
for(int i = 0; i < n; i++) A[i] = B[i] = Complex(0, 0);
for(int i = 0; i < nn; i++) A[i].r = a[i + 1];
for(int i = nn - 1; i >= 0; i--) B[i].r = a[nn - i] * a[nn - i] * a[nn - i];
fft(A, n, 1), fft(B, n, 1);
for(int i = 0; i < n; i++) A[i] = A[i] * B[i];
fft(A, n, -1);
for(int i = 1; i <= n; i++) u3[i] = int(A[i - 1].r + 0.5);
LL ans = 0;
for(int i = 1; i < nn; i++) {
LL o = (LL)i * i;
if(i <= nn / 2) {
int p = u3[i] + u2[i] - u1[i] * 2;
if(p == 0) ans ^= o;
} else {
int p = u3[i] + u2[i] - u1[i] * 2;
if(p)continue;
int k = nn - i; bool bk = 0;
for(int j = k; j < nn; j += k) {
int q = nn - j;
p = u3[q] + u2[q] - u1[q] * 2;
if(p != 0) bk = 1;
} if(!bk) ans ^= o;
}
} printf("%lld\n", ans ^ ((LL)nn * nn));
return 0;
}