CF453D (FWT, 位运算卷积)

image

  • 设num[i]为i的进二进制位上1的个数,这样(u, v)和函数值一一对应起来。
    image

image
原FWT就是循环中一直/2,就是/n

使用简陋版龟速乘

#include<bits/stdc++.h>
#define ll long long
const int N = 5e6 + 7;
const int mod = 998244353;
using namespace std;
ll n, m, t, p;
ll e[N], b[25], num[N];
ll mul(ll a, ll b)
{
    ll z = (long double) a / p * b;
    ll res = (unsigned long long) a * b - (unsigned long long) z * p;
    return (res + p) % p;
}

ll qpow(ll a, ll b)
{
    ll res =  1;
    while(b) {
        if(b & 1) res = mul(res, a);
        a = mul(a, a);
        b >>= 1;
    }
    return res;
}

inline void XOR(ll *f, int x = 1)
{
    for(int o = 2; o <= n; o <<= 1)
        for(int i = 0, k = o >> 1; i < n; i += o)
            for(int j = 0; j < k; ++ j) {
                ll X = f[i + j], Y = f[i + j + k];
                f[i + j] = (X + Y) % p;
                f[i + j + k] = (X - Y % p + p) % p;

            }
    if(x == -1) {
        for(int i = 0; i < n; ++ i) f[i] /= n;
    }
}
int main() {
    cin >> m >> t >> p;
    n = 1 << m;
    p *= n;
    for ( int i = 0; i < n; ++ i ) cin >> e[i], e[i] %= p;
    for ( int i = 0; i <= m; ++ i ) cin >> b[i], b[i] %= p;
    for ( int i = 0; i < n; ++ i ) {
        int sum = __builtin_popcount(i);
        num[i] = b[sum];
    }
    XOR(num), XOR(e);
    for(int i = 0; i < n; ++ i) {
        num[i] = qpow(num[i], t);
        e[i] = mul(e[i], num[i]);
    }
    XOR(e, -1);
    for(int i = 0; i < n; ++ i) {
        printf("%lld\n", e[i]);
    }
    return 0;
}
posted @ 2022-04-25 16:14  qingyanng  阅读(30)  评论(0编辑  收藏  举报