洛谷-4717 【模板】快速沃尔什变换

题目描述
给定长度为 2 n 2^n 2n两个序列 A , B A,B A,B,设 C i ​ = ∑ j ⊕ k = i A j B k C_i​=\sum_{j\oplus k=i}A_jB_k Ci=jk=iAjBk​ 分别当 ⊕ \oplus 是or,and,xor时求出C
输入格式
第一行一个数n。 第二行 2 n 个 数 A 0 . . A 2 n − 1 ​ 2^n个数A_0..A_{2^n-1}​ 2nA0..A2n1第三行 2 n 个 数 B 0 . . B 2 n − 1 2^n个数B_0..B_{2^n-1} 2nB0..B2n1
输出格式
三行每行 2 n 2^n 2n个数,分别代表 ⊕ \oplus 是or,and,xor时 C 0 . . C 2 n − 1 C_0..C_{2^n-1} C0..C2n1​的值   m o d     998244353 \bmod\ 998244353 mod 998244353

输入输出样例
输入 #1
2
2 4 6 8
1 3 5 7

输出 #1
2 22 46 250
88 64 112 56
100 92 68 60

说明/提示
n≤17n。

#include<cstdio>
#include<iostream>
#include<tuple>
#include<algorithm>
using namespace std;
const int mod = 998244353,inv2 = (mod + 1) >> 1;
typedef long long ll;
inline static const void reduce(int&x){x+=x>>31&mod;}
inline static const void mulor(int*a,int*b,int*c,int lm){
    if(!(lm/=2))return void(*c=ll(*a)**b%mod);
    for(int i=0;i<lm;++i)reduce(a[i+lm]+=a[i]-mod),reduce(b[i+lm]+=b[i]-mod);
    mulor(a,b,c,lm),mulor(a+lm,b+lm,c+lm,lm);
    for(int i=0;i<lm;++i)reduce(c[i+lm]-=c[i]);
}
inline static const void muland(int*a,int*b,int*c,int lm){
    if(!(lm/=2))return void(*c=ll(*a)**b%mod);
    for(int i=0;i<lm;++i)reduce(a[i]+=a[i+lm]-mod),reduce(b[i]+=b[i+lm]-mod);
    muland(a,b,c,lm),muland(a+lm,b+lm,c+lm,lm);
    for(int i=0;i<lm;++i)reduce(c[i]-=c[i+lm]);
}
inline static const void mulxor(int*a,int*b,int*c,int lm){
    if(!(lm/=2))return void(*c=ll(*a)**b%mod);
    for(int i=0;i<lm;++i){
        tie(a[i],a[i+lm])=make_tuple(a[i]+a[i+lm],a[i]-a[i+lm]);
        tie(b[i],b[i+lm])=make_tuple(b[i]+b[i+lm],b[i]-b[i+lm]);
        reduce(a[i+lm]),reduce(b[i+lm]),reduce(a[i]-=mod),reduce(b[i]-=mod);
    }
    mulxor(a,b,c,lm),mulxor(a+lm,b+lm,c+lm,lm);
    for(int i=0;i<lm;++i)tie(c[i],c[i+lm])=make_tuple(ll(c[i]+c[i+lm])*inv2%mod,ll(c[i]-c[i+lm]+mod)*inv2%mod);
}
int n;
int a[1 << 17],b[1 << 17],c[1 << 17];
int d[1 << 17],e[1 << 17],f[1 << 17];
int g[1 << 17],h[1 << 17],i[1 << 17];
int main(){
    ios::sync_with_stdio(false),cin.tie(0);
    cin >> n;
    for(int i=0;i<1<<n;++i)cin >> a[i],d[i]=g[i]=a[i];
    for(int i=0;i<1<<n;++i)cin >> b[i],e[i]=h[i]=b[i];
    mulor(a,b,c,1<<n);
    muland(d,e,f,1<<n);
    mulxor(g,h,i,1<<n);
    for(int i=0;i<1<<n;++i)cout << c[i] << ' ';
    cout << '\n';
    for(int i=0;i<1<<n;++i)cout << f[i] << ' ';
    cout << '\n';
    for(int i=0;i<1<<n;++i)cout << ::i[i] << ' ';
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值