CF453D (FWT, 位运算卷积)
- 设num[i]为i的进二进制位上1的个数,这样(u, v)和函数值一一对应起来。
原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;
}