FFT模板(以Rock Paper Scissors为例)
https://cn.vjudge.net/problem/Gym-101667H
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+5;
const double PI = acos(-1.0);
struct cp
{
double a,b;
cp(double x=0.0,double y=0.0):a(x),b(y){};
cp operator +(cp temp)
{
return cp(temp.a+a,temp.b+b);
}
cp operator -(cp temp)
{
return cp(a-temp.a,b-temp.b);
}
cp operator *(cp temp)
{
return cp(temp.a*a-temp.b*b,temp.b*a+temp.a*b);
}
};
int rev[maxn];
void getrev(int bit)
{
for(int i=0;i<(1<<bit);i++)
{
rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
}
}
void fft(cp a[],int n,int dft)
{
for(int i=0;i<n;i++)
{
if(i<rev[i]) swap(a[i],a[rev[i]]);
}
for(int step=1;step<n;step<<=1)
{
cp wn (cos(dft*2*PI/(step*2)),sin(dft*2*PI/(step*2)));
for(int j=0;j<n;j+=step<<1)
{
cp wnk(1.0,0.0);
for(int k=j;k<j+step;k++)
{
cp x = a[k];
cp y = wnk*a[k+step];
a[k] = x+y;
a[k+step] = x-y;
wnk = wnk *wn;
}
}
}
if(dft==-1)
{
for(int i=0;i<n;i++)
{
a[i].a/=n;
}
}
return ;
}
string S,T;
cp s[maxn],t[maxn];
void change(char a,int n,int m)
{
for(int i=0;i<n;i++)
{
s[i].a = (S[i]==a?1.0:0.0);
}
for(int i=0;i<m;i++)
{
t[i].a = (T[i]==a?1.0:0.0);
}
}
int ans[maxn];
int n,m;
void print1()
{
for(int i=0;i<n;i++)
{
cout<<s[i].a<<" ";
}cout<<endl;
}
void print2()
{
for(int i=0;i<m;i++)
{
cout<<t[i].a<<" ";
}cout<<endl;
}
void solve(char a,int len,int n,int m)
{
for(int i=0;i<len;i++)
{
s[i] = cp(0,0);
t[i] = cp(0,0);
}
change(a,n,m);
// print1();
fft(s,len,1);
// print1();
fft(t,len,1);
for(int i=0;i<len;i++)
s[i]=s[i]*t[i];
fft(s,len,-1);
for(int i=m-1;i<len;i++)
{
ans[i]+=int(s[i].a+0.5);
}
}
int main()
{
int i,j,k;
cin>>n>>m>>S>>T;
for(i=0;i<m/2;i++)
{
swap(T[i],T[m-1-i]);
}
char sss[100];
sss['R'-'A']='S';
sss['S'-'A']='P';
sss['P'-'A']='R';
for(i=0;i<m;i++) T[i]=sss[T[i]-'A'];
// cout<<"----------------"<<T<<endl;
int len=2;
for(i=1;(1<<i)<(n+m-1);i++)len<<=1;
getrev(i);
solve('P',len,n,m);
solve('S',len,n,m);
solve('R',len,n,m);
int _max=-1;
for(i=0;i<n+m+1;i++) _max=max(_max,ans[i]);
cout<<_max<<endl;
}
NTT模板
const int mod=998244353;
const int g=3;
int fac[maxn],inv[maxn];
int rev[maxn];
void getRev(int bit){
for(int i=0;i<(1<<bit);i++){
rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
}
}
void NTT(int a[],int n,int o){
for(int i=0;i<n;i++){
if(i<rev[i]) swap(a[i],a[rev[i]]);
}
for(int step=1;step<n;step<<=1){
int Wn=qpow((o==1?g:qpow(g,mod-2)),(mod-1)/(step<<1));
for(int i=0;i<n;i+=(step<<1)){
int w=1;
for(int k=i;k<i+step;k++){
int x=a[k];
int y=1ll*w*a[k+step]%mod;
a[k]=((x+y)%mod+mod)%mod;
a[k+step]=((x-y)%mod+mod)%mod;
w=1ll*w*Wn%mod;
}
}
}
if(o==-1){
long long iv=qpow(n,mod-2);
for(int i=0;i<n;i++)a[i]=1ll*a[i]*iv%mod;
}
}
FWT模板
or
//Log为位数
void FWT(ll *a,int opt) {
for (int bit = 1; bit <= Log; bit++)
for (int i = 0; i < n; i += 1 << bit)
for (int j = i, k = i + (1 << (bit - 1)); k < i + (1 << bit); j++, k++)
{
a[k] += opt*a[j];
if (a[k] >= P) a[k] -= P;
if(a[k]<0) a[k]+=P;
}
}
Q.E.D.