[SOJ #47]集合并卷积
Posted memory-of-winter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SOJ #47]集合并卷积相关的知识,希望对你有一定的参考价值。
题目大意:给你两个多项式$A,B$,求多项式$C$使得:
$$
C_n=sumlimits_{x|y=n}A_xB_y
$$
题解:$FWT$,他可以解决形如$C_n=sumlimits_{xoplus y=n}A_xB_y$的问题,其中$oplus$为位运算(一般为$or,and,xor$)
or:
void FWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) A[i + j + mid] += A[i + j]; } void IFWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) A[i + j + mid] -= A[i + j]; }
and:
void FWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) { int X = A[i + j], Y = A[i + j + mid]; A[i + j] = X + Y, A[i + j + mid] = X - Y; } } void IFWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) { int X = A[i + j], Y = A[i + j + mid]; A[i + j] = X + Y, A[i + j + mid] = X - Y; } for (int i = 0; i < lim; ++i) A[i] /= lim; }
xor:
void FWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) { int X = A[i + j], Y = A[i + j + mid]; A[i + j] = X + Y, A[i + j + mid] = X - Y; } } void IFWT(int *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) { int X = A[i + j], Y = A[i + j + mid]; A[i + j] = X + Y, A[i + j + mid] = X - Y; } for (int i = 0; i < lim; ++i) A[i] /= lim; }
卡点:无
C++ Code:
#include <cstdio> #include <cctype> inline int read() { static int ch; while (isspace(ch = getchar())) ; return ch & 15; } #define N 1048576 int lim; inline void init(const int n) { lim = 1; while (lim < n) lim <<= 1; } inline void FWT(long long *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) A[i + j + mid] += A[i + j]; } inline void IFWT(long long *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) A[i + j + mid] -= A[i + j]; } int n; long long A[N], B[N]; int main() { scanf("%d", &n); for (int i = 0; i < n; ++i) A[i] = read(); for (int i = 0; i < n; ++i) B[i] = read(); init(n); FWT(A), FWT(B); for (int i = 0; i < lim; ++i) A[i] *= B[i]; IFWT(A); for (int i = 0; i < n; ++i) { printf("%lld", A[i]); putchar(i == (n - 1) ? ‘ ‘ : ‘ ‘); } return 0; }
以上是关于[SOJ #47]集合并卷积的主要内容,如果未能解决你的问题,请参考以下文章