zoukankan      html  css  js  c++  java
  • [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;
    }
    

      

  • 相关阅读:
    C/C++动态链接
    通用makefile及解析(转)
    C指针
    C位处理
    C++重载操作符与转换
    吧唧下工作的事情 记用canvas封装的小小控件
    吧唧下工作的事情 平衡图控件
    银行卡验证正则
    element eltable和elpopover 最后一行的 elpopover 有时候点不开的问题
    'CONVERSION_EXIT_CUNIT_OUTPUT'(物料单位转换) SAP
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10259231.html
Copyright © 2011-2022 走看看