题意
数据范围
Analysis
首先分析一下 border b o r d e r 的性质,可以知道,一个长为 len l e n 的 border b o r d e r 代表: ∑leni=0Si=Sn−len+i ∑ i = 0 l e n S i = S n − l e n + i ,那么观察式子,可以发现,事实上一个长为 len l e n 的 border b o r d e r 成立的必要条件,是所有位置对于% (n−len) ( n − l e n ) 分组,在同一组中的字符相等。那么考虑一对 0,1 0 , 1 它们出现的位置为 x,y x , y ,那么所有满足长为 abs(x−y)|(n−len) a b s ( x − y ) | ( n − l e n ) 的 border b o r d e r 都不满足条件。考虑用生成函数来解决问题,设 A(x)=∑n−1i=0[Si==0]xi A ( x ) = ∑ i = 0 n − 1 [ S i == 0 ] x i , B(x)=∑n−1i=0[Sn−i==0] B ( x ) = ∑ i = 0 n − 1 [ S n − i == 0 ] ,那么将这两个多项式乘起来,我们就可以根据每一项系数,来去除不合法的 border b o r d e r ,进而得到答案。
Code
# include<cstdio>
# include<algorithm>
# include<cstring>
using namespace std;
const int N = 5e5 + 5;
typedef long long ll;
const ll mo = 998244353;
const int g = 3;
const int invg = (mo + 1) / 3;
char s[N];
int a[N << 2],b[N << 2],rev[N << 2];
int n,m,l;
inline int pow(int x,int p)
{
int ret = 1;
for (; p ; p >>= 1,x = (ll)x * x % mo)
if (p & 1) ret = (ll)ret * x % mo;
return ret;
}
inline void DFT(int *f,int len,int opt)
{
for (int i = 0 ; i < len ; ++i) if (i < rev[i]) swap(f[i],f[rev[i]]);
for (int i = 1 ; i < len ; i <<= 1)
{
int wn = pow(~opt ? g : invg,(mo - 1) / (i << 1));
for (int j = 0 ; j < len ; j += (i << 1))
{
int w = 1;
for (int k = 0 ; k < i ; ++k,w = (ll)w * wn % mo)
{
int x = f[j + k],y = (ll)w * f[i + j + k] % mo;
f[j + k] = (x + y) % mo,f[i + j + k] = (x - y + mo) % mo;
}
}
}
if (opt == -1)
{
int x = pow(len,mo - 2);
for (int i = 0 ; i < len ; ++i) f[i] = (ll)f[i] * x % mo;
}
}
int main()
{
scanf("%s",s); n = strlen(s);
for (int i = 0 ; i < n ; ++i)
{
a[i] = (s[i] == '0') ? 1 : 0;
b[i] = (s[n - i - 1] == '1') ? 1 : 0;
}
for (m = 1 ; m < (n << 1) ; m <<= 1,++l);
for (int i = 0 ; i < m ; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (l - 1));
DFT(a,m,1); DFT(b,m,1);
for (int i = 0 ; i < m ; ++i) a[i] = (ll)a[i] * b[i] % mo;
DFT(a,m,-1); ll ans = 0;
for (int i = 1 ; i < n ; ++i)
{
bool flag = 1;
for (int j = i ; j < n ; j += i) if (a[n - 1 - j] | a[n - 1 + j]) { flag = 0; break; }
if (flag) ans ^= (ll)(n - i) * (n - i);
}
printf("%lld\n",ans ^ ((ll)n * n));
return 0;
}