题目大意:
给你一个只含 A , B A,B A,B的字符串.问你有多少个间隔为 k k k的字符对满足前一个是 B B B.后一个是 A A A.
题目思路:
发现又是这种只有两种的字符的.显然我们可以直接将字符串当成多项式乘起来.
对于一个 k k k,我们就是要求: ∑ i = 0 n − k − 1 [ s i = = B & & s i + k = A ] \sum_{i=0}^{n-k-1}[s_i==B\&\&s_{i+k}=A] ∑i=0n−k−1[si==B&&si+k=A]
长得有点像卷积,我们对前者,将 B B B置为1. A A A置为0. 对于后者,翻转序列,对 A A A置1. B B B置0.
上述式子就变成了: ∑ i = 0 n − k − 1 s i ∗ t n − k − 1 − i \sum_{i=0}^{n-k-1}s_i*t_{n-k-1-i} ∑i=0n−k−1si∗tn−k−1−i.这不就变成卷积了.直接套板子完事.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 1e6 + 5;
namespace NTT
{
const int P=998244353,g=3;
const int W=22,S=1<<W;
const int J=86583718;
inline int add(int a,int b) {
int r=a+b; return r<P?r:r-P;}
inline int sub(int a,int b) {
int r=a-b; return r<0?r+P:r;}
inline int mul(long long a,long long b) {
return (a*b)%P;}
inline int inv(int a) {
return a==1?a:mul(inv(P%a),P-P/a);}
inline int qpow(int a,long long k)
{
int r=1;
while (k)
{
if (k&1) r=mul(r,a);
k>>=1; a=mul(a,a);
}
return r;
}
const int i2=inv(2),ij=inv(J);
int r[S],w[2][S];
void init(int lim)
{
int w0=qpow(g,(P-1)/lim);
w[0][0]=w[1][0]=1;
for (int i=1;i<lim;i++) w[0][i]=w[1][lim-i]=mul(w[0][i-1],w0);
for (int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void ntt(int *a,int lim,int o)
{
for (int i=0;i<lim;i++) if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=1;i<lim;i<<=1)
{
for (int j=0,t=lim/(i<<1);j<lim;j+=i<<1)
{
for (int k=j,l=0;k<j+i;k++,l+=t)
{
int x=a[k],y=mul(w[o][l],a[k+i]);
a[k]=add(x,y);
a[k+i]=sub(x,y);
}
}
}
if (o)
{
int tmp=NTT::inv(lim);
for (int i=0;i<lim;i++) a[i]=mul(a[i],tmp);
}
}
int p1[S],p2[S];
vector<int>poly_mul(const vector<int>&a,const vector<int>&b)
{
int n=a.size(),m=b.size();
int lim=1;
while (lim<(n<<1)) lim<<=1;
while (lim<(m<<1)) lim<<=1;
init(lim);
copy_n(a.begin(),n,p1); fill(p1+n,p1+lim,0);
copy_n(b.begin(),m,p2); fill(p2+m,p2+lim,0);
ntt(p1,lim,0);
ntt(p2,lim,0);
for (int i=0;i<lim;i++) p1[i]=mul(p1[i],p2[i]);
ntt(p1,lim,1);
return vector<int>(p1,p1+n+m-1);
}
void f_poly_mul(int a[] , int b[] , int n , int m , int res[])
{
int lim=1;
while (lim<(n<<1)) lim<<=1;
while (lim<(m<<1)) lim<<=1;
init(lim);
memcpy(p1 , a , sizeof(int) * n);fill(p1+n,p1+lim,0);
memcpy(p2 , b , sizeof(int) * m);fill(p2+m,p2+lim,0);
ntt(p1,lim,0);
ntt(p2,lim,0);
for (int i=0;i<lim;i++) p1[i]=mul(p1[i],p2[i]);
ntt(p1,lim,1);
for (int i = 0 ; i < n + m ; i++) res[i] = p1[i];
return ;
}
}
int st[maxn] , ss[maxn] , fa[maxn] , fb[maxn] , res[maxn];
char a[maxn] , b[maxn];
int main()
{
scanf("%s" , a);
memcpy(b , a , sizeof a);
int n = strlen(a);
reverse(b , b + n);
for (int i = 0 ; i < n ; i++) fa[i] = a[i] - 'A';
for (int i = 0 ; i < n ; i++) fb[i] = !(b[i] - 'A');
NTT::f_poly_mul(fa , fb , n , n , res);
for (int i = 1 ; i < n ; i++) printf("%d\n" , res[n - i - 1]);
return 0;
}