NTT,FWT模板总结

NTT

洛谷P3803 【模板】多项式乘法(FFT)

const int N = 3 * 1e6 + 10, mod = 998244353, G = 3, Gi = 332748118; 
int n, m, limit = 1, L, r[N];
ll a[N], b[N];
ll ksm(ll a, ll b) {
	ll ret = 1;
	while(b) {
		if(b & 1) ret = (ret * a ) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return ret;
}
void NTT(ll *A, int type) {
	for(int i = 0; i < limit; i++) 
		if(i < r[i]) swap(A[i], A[r[i]]);
	for(int mid = 1; mid < limit; mid <<= 1) {	
		ll Wn = ksm( type == 1 ? G : Gi , (mod - 1) / (mid << 1));
		for(int j = 0; j < limit; j += (mid << 1)) {
			ll w = 1;
			for(int k = 0; k < mid; k++, w = (w * Wn) % mod) {
				 int x = A[j + k], y = w * A[j + k + mid] % mod;
				 A[j + k] = (x + y) % mod,
				 A[j + k + mid] = (x - y + mod) % mod;
			}
		}
	}
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 0; i <= n; i++){
		scanf("%d",&a[i]);
		a[i] = (a[i] + mod) % mod;
	}
	for(int i = 0; i <= m; i++){
		scanf("%d",&b[i]);
		b[i] = (b[i] + mod) % mod;
	}
	while(limit <= n + m) limit <<= 1, L++;
	for(int i = 0; i < limit; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));	
	NTT(a, 1);NTT(b, 1);	
	for(int i = 0; i < limit; i++) a[i] = (a[i] * b[i]) % mod;
	NTT(a, -1);	
	ll inv = ksm(limit, mod - 2);
	for(int i = 0; i <= n + m; i++)
		printf("%d ", (a[i] * inv) % mod);
	return 0;
}

FWT

2020牛客暑期多校训练营(第二场)E Exclusive OR]

自卷最多19次后就不会再产生更大的值。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=998244353;
int N=1<<18;
const int inf=1e9;
ll ksm(ll a,ll b){
	ll ret=1;
	while(b){
		if(b&1) ret=ret*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ret;
}
int inv2=ksm(2,mod-2);
void FWT_or(int *a,int opt)
{
    for(int i=1;i<N;i<<=1)
        for(int p=i<<1,j=0;j<N;j+=p)
            for(int k=0;k<i;++k)
                if(opt==1)a[i+j+k]=(a[j+k]+a[i+j+k])%mod;
                else a[i+j+k]=(a[i+j+k]+mod-a[j+k])%mod;
}
void FWT_and(int *a,int opt)
{
    for(int i=1;i<N;i<<=1)
        for(int p=i<<1,j=0;j<N;j+=p)
            for(int k=0;k<i;++k)
                if(opt==1)a[j+k]=(a[j+k]+a[i+j+k])%mod;
                else a[j+k]=(a[j+k]+mod-a[i+j+k])%mod;
}
void FWT_xor(int *a,int opt)
{
    for(int i=1;i<N;i<<=1)
        for(int p=i<<1,j=0;j<N;j+=p)
            for(int k=0;k<i;++k)
            {
                int X=a[j+k],Y=a[i+j+k];
                a[j+k]=(X+Y)%mod;a[i+j+k]=(X+mod-Y)%mod;
                if(opt==-1)a[j+k]=1ll*a[j+k]*inv2%mod,a[i+j+k]=1ll*a[i+j+k]*inv2%mod;
            }
}
int n,a[1<<19],b[1<<19],ans[200010];
int main(){
	//ios::sync_with_stdio(false);
	//freopen("in","r",stdin);
	scanf("%d",&n);
	rep(i,1,n){
		int x;
		scanf("%d",&x);
		a[x]=b[x]=1;
	}
	FWT_xor(b,1);
	for(int k=1;k<=19;k++){
		rep(i,0,N-1) if(a[i]) ans[k]=i,a[i]=1;
		FWT_xor(a,1);
		rep(i,0,N-1) a[i]=1ll*a[i]*b[i]%mod;
		FWT_xor(a,-1);
	}
	for(int k=20;k<=n;k++) ans[k]=ans[k-2];
	rep(i,1,n) printf("%d%c",ans[i],i==n?'\n':' ');
	return 0;
}

19南昌邀请赛 Another Sequence

FWT+珂朵莉树

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=998244353;
int N=1<<18;
const int inf=1e9;
struct node
{
    ll l,r; //范围
    mutable ll v; //数值
    node(ll L, ll R=-1, ll V=0):l(L), r(R), v(V) {}
    bool operator<(const node& o) const     //重载运算符
    {
        return l < o.l;
    }
};
set<node> s;
#define IT set<node>::iterator  //太长了
IT split(ll pos)
{
    IT it = s.lower_bound(node(pos));   //找到首个不小于pos的set
    if (it != s.end() && it->l == pos)   //无需,直接返回
        return it;
    --it;  //否则一定在前一个区间中
    int L = it->l, R = it->r;  //【l,r】就是要分裂的区间
    ll V = it->v;  //取出值
    s.erase(it);   //删除原集合
    s.insert(node(L, pos-1, V));  //构建前半段的新结合
    return s.insert(node(pos, R, V)).first;  //构建后半段的新集合并且返回地址
}
void assign_val(ll l, ll r, ll val)
{
    IT itr = split(r+1),itl = split(l);  //求出要被摊平区间的收尾地址
    s.erase(itl, itr);  //删除原集合
    s.insert(node(l, r, val));  //添加新集合
}
void add(ll l, ll r)
{
    IT itr = split(r+1),itl = split(l);
    ll cnt=0,mn=0;
    for (; itl != itr; ++itl){
        itl->v =(ll)sqrt(itl->v);
        if(itl->v!=mn){
            mn=itl->v;
            cnt++;
        }
    }
    if(cnt==1) assign_val(l,r,mn);
}
ll qy(ll x){
    IT itr = split(x+1),itl = split(x);
    for (; itl != itr; ++itl){
        return itl->v;
    }
}
void FWT_or(ll *a,int opt)
{
    for(int i=1;i<N;i<<=1)
        for(int p=i<<1,j=0;j<N;j+=p)
            for(int k=0;k<i;++k)
                if(opt==1)a[i+j+k]=a[j+k]+a[i+j+k];
                else a[i+j+k]=(a[i+j+k]-a[j+k]);
}
int n,m;
ll a[1<<19],b[1<<19],l[100010],r[100010],x[100010];
ll c[1000010],tot,f[1000010];
int main(){
	//ios::sync_with_stdio(false);
	//freopen("in","r",stdin);
	scanf("%d",&n);
	rep(i,1,n){
		int x;
		scanf("%d",&x);
		a[x]++;
	}
	rep(i,1,n){
		int x;
		scanf("%d",&x);
		b[x]++;
	}
	scanf("%d",&m);
	FWT_or(a,1);FWT_or(b,1);
	rep(i,0,N-1) a[i]=a[i]*b[i];
	FWT_or(a,-1);
    ll L=0;
	rep(i,0,N-1){
        if(a[i]){
            s.insert(node(L+1,L+a[i],i));
        }
	    L+=a[i];
	}
	rep(i,1,m){
		scanf("%lld",&l[i]);
		if(l[i]==0){
			scanf("%lld",&x[i]);
			printf("%lld\n",qy(x[i]));
		}else{
			scanf("%lld",&r[i]);
			add(l[i],r[i]);
		}
	}
	return 0;
}
posted @ 2020-07-20 23:00  xyq0220  阅读(153)  评论(0编辑  收藏  举报