[FWT] 时隔一年再回首FWT(快速沃尔什变换),我终于不再是个门外汉

时隔一年再回首FWT,我似乎有了新理解??
添加了原理的推导,以前就只有模板…

文章目录

  • 引入
  • or(或)卷积
    • 原理
    • FWT_or正变换
    • FWT_or逆变换
    • 模板
  • and(与)卷积
    • 原理
    • FWT_and正变换
    • FWT_and逆变换
    • 模板
  • xor(异或)卷积
    • 原理
    • FWT_xor正变换
    • FWT_xor逆变换
    • 模板
  • 例题
    • T1:Card Game
    • T2:Tree Cutting

引入

在这里插入图片描述

第一次学习的时候,因为连FFTFFTFFT都没学懂
所以当时学FWTFWTFWT加之是在家里网课
就直接掉线无法连回——一直都是背板子,是完全没学懂啊
最近重新学习了一遍,就马上来完善一下只有模板的博客

学了FFTFFTFFT,我们知道是可以用来算多项式乘法的
h(x)=∑i+j=xf(i)×g(j)h(x)=\sum_{i+j=x}f(i)\times g(j)h(x)=i+j=xf(i)×g(j)
但是可不可以算其他的,改变i,ji,ji,j之间的关系限制呢??
{h(x)=∑i∣j=xf(i)×g(j)h(x)=∑i&j=xf(i)×g(j)h(x)=∑i⊕j=xf(i)×g(j)\left\{ \begin{aligned} h(x)=\sum_{i|j=x}f(i)\times g(j)\\ h(x)=\sum_{i\&j=x}f(i)\times g(j)\\ h(x)=\sum_{i⊕j=x}f(i)\times g(j)\\ \end{aligned} \right.h(x)=ij=xf(i)×g(j)h(x)=i&j=xf(i)×g(j)h(x)=ij=xf(i)×g(j)
|表示二进制或运算&表示二进制与运算表示二进制异或运算

怎么做呢??——还是按着FFTFFTFFT的思路来
考虑能不能将多项式转化一下,变成位对位相乘,最后转化回去就是所求多项式
这就是FWTFWTFWT完成的使命了!!
前人已经找到了规律,备矣,我只是记录规律的正确性
因为模仿FFT,所以n应该也为2的幂,下文意义默认为2的幂


or(或)卷积

原理

求:
h(x)=∑i∣j=xf(i)×g(j)h(x)=\sum_{i|j=x}f(i)\times g(j)h(x)=ij=xf(i)×g(j)
定义多项式AAA转化规律A′[i]=∑i&j=iA[j]A'[i]=\sum_{i\&j=i} A[j]A[i]=i&j=iA[j]


h′[y]=∑x&y=xh[x]h'[y]=\sum_{x\& y=x}h[x]h[y]=x&y=xh[x]=∑x&y=x∑i∣j=xf[i]×g[j]=\sum_{x\& y=x}\sum_{i|j=x}f[i]\times g[j]=x&y=xij=xf[i]×g[j]
i|j=x表明i,j都是x的子集,而x又是y子集⇒\Rightarrowi,jy的子集
=∑i&y=i∑j&y=jf[i]×g[j]=\sum_{i\&y=i}\sum_{j\&y=j}f[i]\times g[j]=i&y=ij&y=jf[i]×g[j]=(∑i&y=if[i])×(∑j&y=jg[j])=(\sum_{i\&y=i}f[i] )\times(\sum_{j\&y=j}g[j])=(i&y=if[i])×(j&y=jg[j])=f′[y]×g′[y]=f'[y]\times g'[y]=f[y]×g[y]
成功实现位对位相乘,yeah!!举国同庆
在这里插入图片描述


最近重温FFT,NTTFFT,NTTFFT,NTT竟然变成了懂原理,看代码看半天??
所以接下来说一下实现,思路是递归,写法是递推,都好懂

FWT_or正变换

考虑模仿FFTFFTFFT,也是不断/2/2/2,将时间复杂度降下去
y<n2y<\frac{n}{2}y<2n,则有
h′[y]=∑x&y=xf[x]×g[x]h'[y]=\sum_{x\& y=x}f[x]\times g[x]h[y]=x&y=xf[x]×g[x]
h′[y+n2]=∑x&(y+n2)=xf[x]×g[x]h'[y+\frac{n}{2}]=\sum_{x\&(y+\frac{n}{2})=x}f[x]\times g[x]h[y+2n]=x&(y+2n)=xf[x]×g[x]
h′[y+n2]h'[y+\frac{n}{2}]h[y+2n]的子集xxx拆分成两类分别考虑
①:x<n2x<\frac{n}{2}x<2n,即二进制最高位是000,则有x&y=x&(y+n2)x\& y=x\&(y+\frac{n}{2})x&y=x&(y+2n)
∑x&y=xf[x]×g[x]=h′[y]\sum_{x\&y=x}f[x]\times g[x]=h'[y]x&y=xf[x]×g[x]=h[y]
②:x>n2x>\frac{n}{2}x>2n
∑x&(y+n2)f[x]×g[x]\sum_{x\&(y+\frac{n}{2})}f[x]\times g[x]x&(y+2n)f[x]×g[x]
将情况②当成新的多项式继续往下FWTFWTFWT,长度砍掉一半,循环上面的操作
最后要将左半部分的答案加到右半部分
🍔
在这里插入图片描述
不断往下,然后把左边蓝色计算出来,再加给右边红色,从下往上递推
在这里插入图片描述

FWT_or逆变换

就是从上往下,先减掉再往下

模板

opt=1opt=1opt=1是正变换

void FWT_or( int *v, int f ) {for( int i = 1;i < n;i <<= 1 )for( int j = 0;j < n;j += ( i << 1 ) )for( int k = 0;k < i;k ++ )v[i + j + k] = ( v[i + j + k] + f * v[j + k] ) % mod;
}

and(与)卷积

原理

问:
h(x)=∑i&j=xf(i)×g(j)h(x)=\sum_{i\&j=x}f(i)\times g(j)h(x)=i&j=xf(i)×g(j)
定义多项式变换规律
A′[i]=∑i&j=iA[j]A'[i]=\sum_{i\&j=i}A[j]A[i]=i&j=iA[j]


h′[y]=∑x&y=yh[x]h'[y]=\sum_{x\&y=y}h[x]h[y]=x&y=yh[x]=∑x&y=y∑i&j=xf[i]×g[j]=\sum_{x\&y=y}\sum_{i\&j=x}f[i]\times g[j]=x&y=yi&j=xf[i]×g[j]
i&j=x说明xi,j的子集,而y又是x的子集⇒\Rightarrowyi,j的子集
=∑i&y=y∑j&y=yf[i]×g[j]=\sum_{i\&y=y}\sum_{j\&y=y}f[i]\times g[j]=i&y=yj&y=yf[i]×g[j]=(∑i&y=yf[i])×(∑j&y=yg[j])=(\sum_{i\&y=y}f[i])\times (\sum_{j\&y=y}g[j])=(i&y=yf[i])×(j&y=yg[j])=f′[y]×g′[y]=f'[y]\times g'[y]=f[y]×g[y]

FWT_and正变换

与FWT_or差不多的思路
y≥n2y\ge \frac{n}{2}y2n
h′[y]=∑x&y=yf[x]×g[x]h'[y]=\sum_{x\&y=y}f[x]\times g[x]h[y]=x&y=yf[x]×g[x]
h′[y−n2]=∑x&(y−n2)=(y−n2)f[x]×g[x]h'[y-\frac{n}{2}]=\sum_{x\&(y-\frac{n}{2})=(y-\frac{n}{2})}f[x]\times g[x]h[y2n]=x&(y2n)=(y2n)f[x]×g[x]
同样的将h′[y−n2]h'[y-\frac{n}{2}]h[y2n]符合条件的xxx分成两类来考虑
①:x≥n2x\ge \frac{n}{2}x2n
说明xxx最高位是111
不考虑xxx的最高位后,y−n2y-\frac{n}{2}y2n仍是其子集
那么yyy也是xxx的子集
∑x&y=yf[x]×g[x]=h′[y]\sum_{x\&y=y}f[x]\times g[x]=h'[y]x&y=yf[x]×g[x]=h[y]
②:x<n2x<\frac{n}{2}x<2n
∑x&(y−n2)=(y−n2)f[x]×g[x]\sum_{x\&(y-\frac{n}{2})=(y-\frac{n}{2})}f[x]\times g[x]x&(y2n)=(y2n)f[x]×g[x]
将此情况当成新的多项式继续往下求解
在这里插入图片描述

🍔:
在这里插入图片描述从下往上算完后将右半部分红色加到左半部分蓝色里,再往上回溯

FWT_and逆变换

从上往下,先左减去右,再下放

模板

void FWT_and( int *v, int f ) {for( int i = 1;i < n;i <<= 1 )for( int j = 0;j < n;j += ( i << 1 ) )for( int k = 0;k < i;k ++ )v[j + k] = ( v[j + k] + v[j + k + i] * f ) % mod;
}

xor(异或)卷积

在这里插入图片描述

原理

问:
h(x)=∑i⊕j=xf(i)×g(j)h(x)=\sum_{i⊕j=x}f(i)\times g(j)h(x)=ij=xf(i)×g(j)
定义多项式变换规律
A′[i]=∑cnt(i&j1)%2=0A[j1]−∑cnt(i&j2)%2=1A[j2]A'[i]=\sum_{cnt(i\&j_1)\%2=0}A[j_1]-\sum_{cnt(i\&j_2)\%2=1}A[j_2]A[i]=cnt(i&j1)%2=0A[j1]cnt(i&j2)%2=1A[j2]
cnt(i)cnt(i)cnt(i)表示iii二进制有多少个111
在这里插入图片描述
h′[y]=∑cnt(y&x1)%2=0h[x1]−∑cnt(y&x2)%2=1h[x2]h'[y]=\sum_{cnt(y\&x_1)\%2=0}h[x_1]-\sum_{cnt(y\&x_2)\%2=1}h[x_2]h[y]=cnt(y&x1)%2=0h[x1]cnt(y&x2)%2=1h[x2]=∑cnt(y&x1)%2=0∑i1⊕j1=x1f[i1]×g[j1]−∑cnt(y&x2)%2=1∑i2⊕j2=x2f[i2]×g[j2]=\sum_{cnt(y\&x_1)\%2=0}\sum_{i_1⊕j_1=x_1}f[i_1]\times g[j_1]-\sum_{cnt(y\&x_2)\%2=1}\sum_{i_2⊕j_2=x_2}f[i_2]\times g[j_2]=cnt(y&x1)%2=0i1j1=x1f[i1]×g[j1]cnt(y&x2)%2=1i2j2=x2f[i2]×g[j2]
在这里插入图片描述似乎卡住了,推不下去了??这可不行,证明不了正确性啊!
那没办法了,正着推不下去,老子倒着往回退可还行
仗着前人的正确性疯狂整
f′[x]×g′[x]f'[x]\times g'[x]f[x]×g[x]=(∑f[i]−∑f[j])×(∑g[i]−∑g[j])=(\sum f[i]-\sum f[j])\times (\sum g[i]-\sum g[j])=(f[i]f[j])×(g[i]g[j])cnt(x&i)%2=0,cnt(x&j)%2=1cnt(x\& i)\%2=0,cnt(x\&j)\%2=1cnt(x&i)%2=0,cnt(x&j)%2=1=∑f[i]g[i]+∑f[j]g[j]−∑f[i]g[j]−∑f[j]g[i]=\sum f[i]g[i]+\sum f[j]g[j]-\sum f[i]g[j]-\sum f[j]g[i]=f[i]g[i]+f[j]g[j]f[i]g[j]f[j]g[i]
这里需要抽象理解式子,才能建立关联,发现与h′[x]h'[x]h[x]展开是一致的


不好意思我太菜了,建立不了关联——那就换一种证法
在这里插入图片描述

x&(i⊕j)≡x&i+x&j(mod2)x\&(i⊕j)\equiv x\& i+x\&j\ \ \ \ (mod\ \ \ 2)x&(ij)x&i+x&j    (mod   2)
我们采取暴力分类讨论智障求证,下面i,j,x均表示其二进制某一位上为1/01/01/0

  1. i=1,j=1,x=0
    i⊕j=0,(i⊕j)&x=0i⊕j=0,(i⊕j)\&x=0ij=0,(ij)&x=0
    x&i=0,x&j=0,x&i+x&j=0x\&i=0,x\&j=0,x\&i+x\&j=0x&i=0,x&j=0,x&i+x&j=0
  2. i=0,j=0,x=0
    i⊕j=0,(i⊕j)&x=0i⊕j=0,(i⊕j)\&x=0ij=0,(ij)&x=0
    x&i=0,x&j=0,x&i+x&j=0x\&i=0,x\&j=0,x\&i+x\&j=0x&i=0,x&j=0,x&i+x&j=0
  3. i=1,j=0,x=0
    i⊕j=1,(i⊕j)&x=0i⊕j=1,(i⊕j)\&x=0ij=1,(ij)&x=0
    x&i=0,x&j=0,x&i+x&j=0x\&i=0,x\&j=0,x\&i+x\&j=0x&i=0,x&j=0,x&i+x&j=0
  4. i=0,j=1,x=0
    i⊕j=1,(i⊕j)&x=0i⊕j=1,(i⊕j)\&x=0ij=1,(ij)&x=0
    x&i=0,x&j=0,x&i+x&j=0x\&i=0,x\&j=0,x\&i+x\&j=0x&i=0,x&j=0,x&i+x&j=0
  5. i=0,j=0,x=1
    i⊕j=0,(i⊕j)&x=0i⊕j=0,(i⊕j)\&x=0ij=0,(ij)&x=0
    x&i=0,x&j=0,x&i+x&j=0x\&i=0,x\&j=0,x\&i+x\&j=0x&i=0,x&j=0,x&i+x&j=0
  6. i=0,j=1,x=1
    i⊕j=1,(i⊕j)&x=1i⊕j=1,(i⊕j)\&x=1ij=1,(ij)&x=1
    x&i=0,x&j=1,x&i+x&j=1x\&i=0,x\&j=1,x\&i+x\&j=1x&i=0,x&j=1,x&i+x&j=1
  7. i=1,j=0,x=1
    i⊕j=1,(i⊕j)&x=1i⊕j=1,(i⊕j)\&x=1ij=1,(ij)&x=1
    x&i=1x&j=0,x&i+x&j=1x\&i=1x\&j=0,x\&i+x\&j=1x&i=1x&j=0,x&i+x&j=1
  8. i=1,j=1,x=1
    i⊕j=0,(i⊕j)&x=0i⊕j=0,(i⊕j)\&x=0ij=0,(ij)&x=0
    x&i=1,x&j=1,x&i+x&j=2x\&i=1,x\&j=1,x\&i+x\&j=2x&i=1,x&j=1,x&i+x&j=2
    此情况注意是在取模2下,所以奇偶还是没变

A′A'A换一种表达方式
A′[i]=∑(−1)cnt(i&j)%2A[j]A'[i]=\sum (-1)^{cnt(i\&j)\% 2}A[j]A[i]=(1)cnt(i&j)%2A[j]
重新推一遍式子
科研就是不断失败重头再来!!
h′[y]=∑(−1)cnt(y&x)%2h[x]=∑(−1)cnt(y&x)%2∑i⊕j=xf[i]g[j]h'[y]=\sum(-1)^{cnt(y\&x)\%2}h[x]=\sum(-1)^{cnt(y\&x)\%2}\sum_{i⊕j=x}f[i]g[j]h[y]=(1)cnt(y&x)%2h[x]=(1)cnt(y&x)%2ij=xf[i]g[j]=∑(−1)cnt(y&(i⊕j))%2f[i]g[j]=∑(−1)cnt(y&i)+cnt(y&j)f[i]g[j]=\sum (-1)^{cnt(y\&(i⊕j))\%2}f[i]g[j]=\sum (-1)^{cnt(y\&i)+cnt(y\&j)}f[i]g[j]=(1)cnt(y&(ij))%2f[i]g[j]=(1)cnt(y&i)+cnt(y&j)f[i]g[j]=∑(−1)cnt(y&i)f[i]×∑(−1)cnt(y&j)g[j]=\sum (-1)^{cnt(y\&i)}f[i]\times \sum (-1)^{cnt(y\&j)}g[j]=(1)cnt(y&i)f[i]×(1)cnt(y&j)g[j]=f′[y]×g′[y]=f'[y]\times g'[y]=f[y]×g[y]
在这里插入图片描述


FWT_xor正变换

有了前面两种简单的铺垫,这里的思路是一致的,不再写式子

y<n2y<\frac{n}{2}y<2n
将符合条件的xxx同样分成两类
①:x<n2x<\frac{n}{2}x<2n
②:x≥n2x\ge \frac{n}{2}x2n
x&yx\&yx&y111个数的奇偶性并没有发生改变
直接加起来

y≥n2y\ge \frac{n}{2}y2n
将符合条件的xxx同样分成两类
①:x<n2x<\frac{n}{2}x<2n
②:x≥n2x\ge \frac{n}{2}x2n
情况②的x&yx\&yx&y最高位为111,个数奇偶性发生改变,前面带的符号变成负号
FWT(A)=(FWT(B)+FWT(C),FWT(B)−FWT(C))FWT(A)=(FWT(B)+FWT(C),FWT(B)-FWT(C))FWT(A)=(FWT(B)+FWT(C)FWT(B)FWT(C))

FWT_xor逆变换

就相当于解一个二元一次方程,已知和差
IFWT(A)=(IFWT(B)+IFWT(C)2,IFWT(B)−IFWT(C)2)IFWT(A)=(\frac{IFWT(B)+IFWT(C)}{2},\frac{IFWT(B)-IFWT(C)}{2})IFWT(A)=(2IFWT(B)+IFWT(C),2IFWT(B)IFWT(C))

模板

void FWT_xor( int *v, int f ) {for( int i = 1;i < n;i <<= 1 )for( int j = 0;j < n;j += ( i << 1 ) ) for( int k = 0;k < i;k ++ ) {int x = v[j + k], y = v[j + k + i];v[j + k] = ( x + y ) % mod;v[j + k + i] = ( x - y + mod ) % mod;if( f == -1 ) {v[j + k] = v[j + k] * inv % mod;v[j + k + i] = v[j + k + i] * inv % mod;}}
}

例题

听得懂原理:理解记忆模板
听不懂:强化训练
在这里插入图片描述

T1:Card Game

title
Alice and Bob now love to play a card game. Everyone is starting n cards, each card has no more than m attribute. Now they need finish Q tasks, each task will require everyone to give a card, and then make up the attribute types that the task demands (e.g. the task required attributes A, B, C, Alice’s card contains A B and Bob’s card contains B, C. they can use this union to finish the task).
For each task, How many ways that Alice and Bob can do this task.
Input
here are T cases. (T<=20) (about 5 test cases n>=1000 m>=12 Q>=1000)
For each test case.The first line contains two integers n,m(n<=100000, m<=18), which indicates the number of cards which each one has and total attributes.
The next line contain n binary numbers indicates the cards Alice has. The ith binary number m_i indicates the attributes each card have. (m_i <2^18)
(if m_i = 10011 , this card has the first, second and fifth attrtbutes)
he next line contain n binary numbers indicates the cards Bob has.
Then contain one integer Q which is the number of Tasks.
Then next Q lines, each contain one binary number q_i which indicates the attributes they need to make. (qi < 2^18)
Output
For each test case, you first output one line “Case #%d:”
Then output q lines, each line contains one which indicates the ways they can finish this task.
Sample Input

1
4 4
1001 11 1100 1000
1110 1001 10 100
2
1100
111

Sample Output

Case #1:
2
1

solution
板题,就是套FWT_orFWT\_orFWT_or
code

#include <cstdio>
#include <cstring>
#define mod 998244353
#define MAXN 200000
int n, m, N, Q;
long long A[MAXN], B[MAXN], v[MAXN], c[MAXN];
long long inv = ( mod + 1 ) >> 1;
char s[30];long long read() {scanf( "%s", s );int len = strlen( s );long long x = 0;for( int i = 0;i < len;i ++ )x = ( x << 1 ) + ( s[i] - '0' );return x;
}void FWT_or( long long *v, int opt ) {for( int i = 2;i <= N;i <<= 1 )for( int p = i >> 1, j = 0;j < N;j += i )for( int k = j;k < j + p;++ k )v[k + p] += v[k] * opt;
}int main() {int T, n, m;scanf( "%d", &T );for( int t = 1;t <= T;t ++ ) {printf( "Case #%d:\n", t );scanf( "%d %d", &n, &m );N = 1 << m;memset( A, 0, sizeof( A ) );memset( B, 0, sizeof( B ) );for( int i = 1;i <= n;i ++ ) A[read()] ++;for( int i = 1;i <= n;i ++ ) B[read()] ++;FWT_or( A, 1 ), FWT_or( B, 1 );for( int i = 0;i < N;i ++ )A[i] = A[i] * B[i];FWT_or( A, -1 );scanf( "%d", &Q );while( Q -- ) printf( "%lld\n", A[read()] );}return 0;
}

T2:Tree Cutting

title
Byteasar has a tree TTT with nnn vertices conveniently labeled with 1,2,...,n1,2,...,n1,2,...,n. Each vertex of the tree has an integer value viv_ivi.
The value of a non-empty tree TTT is equal to v1⊕v2⊕...⊕vnv_1\oplus v_2\oplus ...\oplus v_nv1v2...vn, where ⊕\oplus denotes bitwise-xor.
Now for every integer kkk from [0,m)[0,m)[0,m), please calculate the number of non-empty subtree of TTT which value are equal to kkk.
A subtree of TTT is a subgraph of TTT that is also a tree.
Input
The first line of the input contains an integer T(1≤T≤10)T(1\leq T\leq10)T(1T10), denoting the number of test cases.
In each test case, the first line of the input contains two integers n(n≤1000)n(n\leq 1000)n(n1000) and m(1≤m≤210)m(1\leq m\leq 2^{10})m(1m210), denoting the size of the tree TTT and the upper-bound of vvv.
The second line of the input contains nnn integers v1,v2,v3,...,vn(0≤vi<m)v_1,v_2,v_3,...,v_n(0\leq v_i < m)v1,v2,v3,...,vn(0vi<m), denoting the value of each node.
Each of the following n−1n-1n1 lines contains two integers ai,bia_i,b_iai,bi, denoting an edge between vertices aia_iai and bi(1≤ai,bi≤n)b_i(1\leq a_i,b_i\leq n)bi(1ai,bin).
It is guaranteed that mmm can be represent as 2k2^k2k, where kkk is a non-negative integer.
Output
For each test case, print a line with mmm integers, the iii-th number denotes the number of non-empty subtree of TTT which value are equal to iii.
The answer is huge, so please module 109+710^9+7109+7.
Sample Input

2
4 4
2 0 1 3
1 2
1 3
1 4
4 4
0 1 3 1
1 2
1 3
1 4

Sample Output

3 3 2 3
2 4 2 3

solution
dp[u][i]dp[u][i]dp[u][i]:表示以uuu为根的子树内,异或值为jjj的方案数
有一个很暴力的转移
dp[u][i]=∑j⊗k=idp[u][j]∗dp[v][k],v∈son[u]dp[u][i]=\sum_{j\otimes k=i}dp[u][j]*dp[v][k],v∈son[u]dp[u][i]=jk=idp[u][j]dp[v][k]vson[u]
发现直接可以FWT_xorFWT\_xorFWT_xor,直接dfsdfsdfs暴力做就降了一个mmm
code

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define mod 1000000007
#define ll long long
#define MAXN 1050
vector < int > G[MAXN]; 
const ll inv = ( mod + 1 ) >> 1;
int T, n, m, N;
ll ans[MAXN];
ll dp[MAXN][MAXN];void FWT( ll *w, int opt ) {for( int i = 2;i <= N;i <<= 1 )for( int p = i >> 1, j = 0;j < N;j += i )for( int k = j;k < j + p;k ++ ) {ll x = w[k], y = w[k + p];w[k] = ( x + y ) % mod;w[k + p] = ( x - y + mod ) % mod;if( opt == -1 )w[k] = w[k] * inv % mod, w[k + p] = w[k + p] * inv % mod;}
}void dfs( int u, int fa ) {FWT( dp[u], 1 );for( int i = 0;i < G[u].size();i ++) {int v = G[u][i];if( v == fa ) continue;dfs( v, u );for( int j = 0;j < N;j ++ )dp[u][j] = dp[u][j] * dp[v][j] % mod;}FWT( dp[u], -1 );dp[u][0] = ( dp[u][0] + 1 ) % mod;//一个子树是可以不选的 所以要+1FWT( dp[u], 1 ); 
}int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d %d", &n, &m );memset( dp, 0, sizeof( dp ) );memset( ans, 0, sizeof( ans ) );for( int i = 1;i <= n;i ++ ) G[i].clear();N = m;for( int i = 1, x;i <= n;i ++ )scanf( "%d", &x ), dp[i][x] ++;for( int i = 1, u, v;i < n;i ++ ) {scanf( "%d %d", &u, &v );G[u].push_back( v ), G[v].push_back( u );}dfs( 1, 0 );for( int i = 1;i <= n;i ++ )FWT( dp[i], -1 );for( int i = 1;i <= n;i ++ )dp[i][0] = ( dp[i][0] - 1 + mod ) % mod;for( int i = 1;i <= n;i ++ )for( int j = 0;j < m;j ++ )ans[j] = ( ans[j] + dp[i][j] ) % mod;printf( "%lld", ans[0] );for( int i = 1;i < m;i ++ )printf( " %lld", ans[i] ); printf( "\n" );}	return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317906.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模板:多项式乘法(FFTNTT)

文章目录前言系数表示法和点值表示法单位根离散傅立叶变换&#xff08;DFT&#xff09;位逆序置换&#xff08;蝴蝶变换&#xff09;离散傅立叶逆变换&#xff08;IDFT&#xff09;代码NTT代码所谓快速傅立叶变换&#xff0c;就是傅立叶发明的一种快速的变换 &#xff08;逃&am…

Loj #149. 01 分数规划(01分数规划模板题)

链接 题意&#xff1a; 题解&#xff1a; 详细解法看这里 这里说个点&#xff0c;eps一定要开足够小&#xff0c;我一开始开的1e-5&#xff0c;结果就过了90%的数据&#xff0c;开到1e-7就足够了 代码&#xff1a; #include<bits/stdc.h> typedef long long ll; usin…

CF986C AND Graph(图论+二进制连边)

CF986C AND Graph \(\color{yellow}{\bigstar\texttt{Hint}}\)&#xff1a;和每个点连接的点是这个数取反后的子集&#xff0c;考虑将这个点和它的反连边&#xff0c;那么所有对应的数的子集都是同一个连通块内的。 之后的一种简单的寻找连通块就是直接对所有没有访问过的点暴力…

AT2376-[AGC014D]Black and White Tree【结论,博弈论】

正题 题目链接:https://www.luogu.com.cn/problem/AT2376 题目大意 给出nnn个点的一棵树&#xff0c;先后手轮流选择一个未染色的点染上白色(先手)/黑色(后手)&#xff0c;如果最后有一个白色的点连接的都是白色的点则先手获胜&#xff0c;否则后手获胜。求是否先手必胜。 1≤…

如何测试 ASP.NET Core Web API

在本文中&#xff0c;我们将研究如何测试你的 ASP .NET Core 2.0 Web API 解决方案。我们将了解使用单元测试进行内部测试&#xff0c;使用全新的 ASP .NET Core 的集成测试框架来进行外部测试。本文要点正确理解并使用单元测试和你的 ASP .NET Core Web API 解决方案一样重要。…

[帝皇杯day 1] [NOIP2018模拟赛]小P的loI(暴力+素筛),【NOIP模拟赛】创世纪(贪心),无聊的数对(线段树)

文章目录T1&#xff1a;小P的loltitlesolutioncodeT2&#xff1a;创世纪titlesolutioncodeT3&#xff1a;无聊的数对titlesolutioncodeT1&#xff1a;小P的lol title solution 此题非常水… 先用素数筛&#xff0c;筛出[1,n][1,n][1,n]中的质数 质数越小&#xff0c;倍数的分…

P6144 [USACO20FEB]Help Yourself P(DP+线段树)

P6144 [USACO20FEB]Help Yourself P 将线段按照了 \(r\) 排序&#xff0c;设右端点为 \(r\) 的答案为 \(f_r\)&#xff0c;发现这样转移非常困难。 \(\color{yellow}{\bigstar\texttt{Trick}}\)&#xff1a;区间覆盖的题要按照左端点排序&#xff0c;记右端点为 \(r\) 时的答案…

Desert King POJ - 2728

题意&#xff1a; 给定N个平面上的点的坐标和它们的权值&#xff0c;任意两点之间的边的价值是它们的距离&#xff0c;费用是两点权值之差的绝对值&#xff0c;求该图的一棵生成树&#xff0c;使得该树所有边的费用之和与价值之和的比值最小&#xff08;只需求这个比值即可&am…

洛谷P3338:力(FFT)

传送门 解析 算是比较适合的FFT入门题了吧 一个重要的trick&#xff1a; 当函数无法表示成卷积时&#xff0c;可以把函数翻转过来 然后调一调就又是卷积了 一个重要的注意事项是FFT的lim一定是两多项式相乘结果多项式的项数&#xff01; 即使后面的项根本没有用也一样 其他的…

CF650E-Clockwork Bomb【并查集】

正题 题目链接:https://www.luogu.com.cn/problem/CF650E 题目大意 给出nnn个点的两棵树&#xff0c;你每次可以选择第一棵树上的一条边改成另一条边&#xff0c;但是改完之后必须还是一棵树&#xff0c;求最少的步数把第一棵树改成第二棵树。 1≤n≤51051\leq n\leq 5\times…

[2-sat专练]poj 3683,hdu 1814,hdu 1824,hdu 3622,hdu 4115,hdu 4421

文章目录Priest Johns Busiest DaycodePeaceful CommissioncodeLets go homecodeBomb GamecodeEliminate the ConflictcodeBit MagiccodePriest John’s Busiest Day 题目 司仪必须在婚礼开始或结束时出现&#xff0c;考虑把第iii场婚礼拆成两个点 iii&#xff1a;表示司仪在婚…

.NET Core中的一个接口多种实现的依赖注入与动态选择

最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式&#xff0c;为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中&#xff0c;但是在服务调用的时候总是获取到最后注入的那个方法的实现&#xff0c;这时候就在想能不能实现动态的选…

Sightseeing Cows POJ - 3621

题意&#xff1a; L个点&#xff0c;P边的点边带权的有向图&#xff0c;求一个环点权和与边权和比值的最大值。 题解&#xff1a; 01分数规划判负环 详细看这里 还是套用01分数规划模型&#xff0c;点权为value[i],边权为cost[u],一个环为C&#xff0c;问题要求最大化 最…

CF559E Gerald and Path(DP)

CF559E Gerald and Path 设 \(dp(i,p)\) 表示完成前 \(i\) 条线段的覆盖&#xff0c;最右端位于 \(p\) 点的最大收益。 转移&#xff1f;向下一条线段转移时加上他们中间的距离&#xff1f;发现这样没有办法统计 \(p\) 点以前的空位了&#xff01; \(\color{yellow}{\bigstar\t…

多项式乘法:练习总结

文章目录前言力代码礼物代码差分和前缀和代码开拓者的知识代码总结前言 这两天由于国庆集训全是阴间的生成函数&#xff0c;所以就学了一点点相关的内容 其实就学了个FFT和NTT 也算是点开了一个小小的技能点吧 进入多项式才发现里面世界的广阔 然而由于这玩意没有一个是NOIP考…

CF1444C-Team-Building【可撤销并查集】

正题 题目链接:https://www.luogu.com.cn/problem/CF1444C 题目大意 给出nnn个点mmm条边的一张图&#xff0c;总共kkk个颜色&#xff0c;每个点有一个颜色。 询问有多少无序颜色对(x,y)(x,y)(x,y)满足x≠yx\neq yx​y且颜色为xxx或yyy的点构成的生成子图是一个二分图。 1≤…

C# Memory Cache 踩坑记录

背景前些天公司服务器数据库访问量偏高,运维人员收到告警推送,安排我团队小伙伴排查原因.我们发现原来系统定期会跑一个回归测试,该测运行的任务较多,每处理一条任务都会到数据库中取相关数据,高速地回归测试也带来了高频率的数据库读取.解决方案1我们认为每个任务要取的数据大…

模板:无旋treap

文章目录前言操作合并分裂插入删除查找第k大查询x的排名前驱后继完整代码所谓无旋treap&#xff0c;就是不带旋转的treap 前言 现在“理论上”我会四种平衡树了 之前说无旋treap功能弱&#xff0c;是我狗眼看银低了qwq 这玩意区间上该搞的也能搞 而且确实是非常的 好写&#x…

[贪心专题]CF549G,CF351E,CF226D,CF1276C,CF1148E,CF798D

文章目录T1&#xff1a;CF1276C Beautiful RectangletitlesolutioncodeT2&#xff1a;CF226D The tabletitlesolutioncodeT3&#xff1a;CF549G Happy LinetitlesolutioncodeT4&#xff1a;CF798D Mike and distributiontitlesolutioncodeT5&#xff1a;CF351E Jeff and Permut…

51nod1766-树上的最远点对【结论,线段树】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1766 题目大意 给出nnn个点的一棵树&#xff0c;mmm次询问给出两个区间&#xff0c;要求在两个区间中各选一个点使得他们之间距离最大。 1≤n,m≤1051\leq n,m\leq 10^51≤n,m≤105 解题思路 结论就是两…