High-dimensional convolution theory & FWT study notes

Before done so much to generate topics and polynomial function convolution, the result was today understand the essence optimized convolution algorithm.


First of all we have to binary FWT or start with a simple example.

We found a positive FWT or transformation is seeking $ \ hat {a} _j = \ sum_ {i \ in j} a_i $, and that is a subset of, then this is how to do?

We assume that the $ A $ $ \ hat {a} $ transfer matrix $ X $, then

$$(\sum_{j}X_{i,j}a_j)*(\sum_{j}X_{i,j}b_j)=\sum_jX_{i,j}(\sum_{s|t=j}a_sb_t)$$

So consider the contribution of $ a_sb_t $.

$$X_{i,s}*X_{i,t}=X_{i,s|t}$$

So for each row of X-$ $ has $ X_s * X_t = X_ {s | t} $

And finally, due to the inverse transform, which is multiplied by $ X ^ {- 1} $, we can know the inverse matrix if and only if $ X $ of determinant is not zero, so any two lines of $ X $ not the same.

According to this, we assume that only $ 0 and $ X-1 (since this is the simplest), then $ X_ {s | t} = 1 $ and $ X_s = X_t = 1 $ equivalent, it may be introduced a.

Look $ $ n = 8 in the case.

$$X=\begin{pmatrix}1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 \\1 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\1 & 1 & 0 & 0 & 1 & 1 & 0 & 0 \\1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\1 & 1 & 1 & 1 & 1 & 1 & 1 & 1\end{pmatrix}$$

Hit the table to find the law available

$$X_{i,j}=\prod_{k=0}^{n-1}C_{i[2^k],j[2^k]}$$

Where $ i [2 ^ k] $ $ I $ represented in binary bits of $ k $.

$$C=\begin{pmatrix}1 & 1 \\ 0 & 1\end{pmatrix}$$

Then we will know how to divide and conquer the calculation of the matrix vector multiply. (Yes, that triple loop)


We can also FFT matrix also write out.

$$A=\begin{pmatrix}\omega_n^0 & \omega_n^0 & \ldots & \omega_n^0 & \omega_n^0 \\\omega_n^0 & \omega_n^1 & \ldots & \omega_n^{n-2} & \omega_n^{n-1} \\\vdots & \vdots & \ddots & \ddots & \ddots \\\omega_n^0 & \omega_n^{n-1} & \ldots & \omega_n^{(n-2)(n-1)} & \omega_n^{(n-1)(n-1)}\end{pmatrix}$$

I.e., $ A_ {i, j} = \ omega_n ^ {ij} $, so

$$A^{-1}=\frac{1}{n}\begin{pmatrix}\omega_n^{-0} & \omega_n^{-0} & \ldots & \omega_n^{-0} & \omega_n^{-0} \\\omega_n^{-0} & \omega_n^{-1} & \ldots & \omega_n^{-(n-2)} & \omega_n^{-(n-1)} \\\vdots & \vdots & \ddots & \ddots & \ddots \\\omega_n^{-0} & \omega_n^{-(n-1)} & \ldots & \omega_n^{-(n-2)(n-1)} & \omega_n^{-(n-1)(n-1)}\end{pmatrix}$$

即$A^{-1}_{i,j}=\frac{\omega_n^{-ij}}{m}$


UOJ272 [2016] Shijiazhuang Tsinghua training of the working class were stronger

We set $ B_ {i, j} $ represents $ f_ {i-1} $ to $ $ F_i transition matrix.

Defined $ a \ oplus b $ represents ternary not carry adder , $ a \ ominus b $ represents ternary subtraction not step down . Easy to get these two operations are inverse operations.

The $ \ forall k, B_ {i \ oplus k, j \ oplus k} = B_ {i, j} $, obtained by the mathematical induction $ \ forall k, B_ {i \ oplus k, j \ oplus k} ^ n = B_ {i, j} ^ n $ i.e. $ B_ {i, j} ^ n = B_ {0, j \ ominus i} ^ n $

$$f_{n,i}=\sum_{j}f_{0,j}*B_{j,i}^n=\sum_{j}f_{0,j}*B_{0,i\ominus j}^n=\sum_{x\oplus y=i}f_x*B_{0,y}^n$$

So we simply requires the first row of the matrix and $ B $ and $ f_0 $ do XOR convolution in the ternary it.

We first consider binary.

$$C=\begin{pmatrix}1 & 1 \\1 & -1\end{pmatrix}$$

(Meaning $ C $ matrix see above)

So emotional understanding of what (or you can push yourself a push), XOR convolution matrix ternary is:

$$C=\begin{pmatrix}1 & 1 & 1 \\1 & \omega & \omega^2 \\1 & \omega^2 & \omega\end{pmatrix}$$

$$C^{-1}=\frac{1}{3}\begin{pmatrix}1 & 1 & 1 \\1 & \omega^2 & \omega \\1 & \omega & \omega^2\end{pmatrix}$$

Where $ \ omega = \ frac {-1+ \ sqrt {3} i} {2} $

But $ \ sqrt {3} $ operation is very troublesome, but also has accuracy problems, we get $ 1, \ omega $ as a base instead of $ 1, i $, i.e. the complex representation as $ a b \ the form + omega $ a.

Multiplication $ a + bi $ multiplication is not the same need to push a push.

$$(a+b\omega)(c+d\omega)=ac+(bc+ad)\omega+bd(-\omega-1)=(ac-bd)+(bc+ad-bd)\omega$$

Then it should be done.

 1 #include<cstdio>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 531441;
 6 int n, m, t, p, po[13], cntx[N], cnty[N];
 7 inline void exgcd(int a, int b, int &x, int &y){
 8     if(!b){x = 1; y = 0; return;}
 9     exgcd(b, a % b, y, x); y -= (LL) a / b * x;
10 }
11 struct complex {
12     int x, y;
13     inline complex(int x = 0, int y = 0): x(x), y(y){}
14     inline complex operator + (const complex &o) const {return complex((x + o.x) % p, (y + o.y) % p);}
15     inline complex operator - (const complex &o) const {return complex((x - o.x + p) % p, (y - o.y + p) % p);}
16     inline complex operator * (const complex &o) const {
17         return complex(((LL) x * o.x % p - (LL) y * o.y % p + p) % p, ((LL) y * o.x % p + (LL) x * o.y % p - (LL) y * o.y % p + p) % p);
18     }
19 } A[N], B[N];
20 inline complex kasumi(complex a, int b){
21     complex res = complex(1, 0);
22     while(b){
23         if(b & 1) res = res * a;
24         a = a * a;
25         b >>= 1;
26     }
27     return res;
28 }
29 inline complex calc1(const complex &a){return complex((p - a.y) % p, (a.x - a.y + p) % p);}
30 inline complex calc2(const complex &a){return complex((a.y - a.x + p) % p, (p - a.x) % p);}
31 inline void dft(complex *A){
32     for(Rint mid = 1;mid < n;mid *= 3)
33         for(Rint j = 0;j < n;j += mid * 3)
34             for(Rint k = 0;k < mid;k ++){
35                 complex x = A[j + k], y = A[j + k + mid], z = A[j + k + mid * 2];
36                 A[j + k] = x + y + z;
37                 A[j + k + mid] = x + calc1(y) + calc2(z);
38                 A[j + k + mid * 2] = x + calc1(z) + calc2(y);
39             }
40 }
41 inline void idft(complex *A){
42     for(Rint mid = 1;mid < n;mid *= 3)
43         for(Rint j = 0;j < n;j += mid * 3)
44             for(Rint k = 0;k < mid;k ++){
45                 complex x = A[j + k], y = A[j + k + mid], z = A[j + k + mid * 2];
46                 A[j + k] = x + y + z;
47                 A[j + k + mid] = x + calc1(z) + calc2(y);
48                 A[j + k + mid * 2] = x + calc1(y) + calc2(z);
49             }
50 }
51 int trans[13][13];
52 int main(){
53     scanf("%d%d%d", &m, &t, &p);
54     po[0] = 1;
55     for(Rint i = 1;i <= m;i ++) po[i] = (LL) po[i - 1] * 3;
56     n = po[m];
57     for(Rint i = 1;i <= m;i ++) po[i] %= p;
58     if(p == 1){
59         for(Rint i = 0;i < n;i ++) puts("0");
60         return 0;
61     }
62     for(Rint i = 0;i < n;i ++) scanf("%d", &A[i].x);
63     for(Rint i = 0;i <= m;i ++)
64         for(Rint j = 0;i + j <= m;j ++) scanf("%d", trans[i] + j);
65     for(Rint i = 0;i < n;i ++){
66         cntx[i] = cntx[i / 3] + (i % 3 == 1);
67         cnty[i] = cnty[i / 3] + (i % 3 == 2);
68         B[i].x = trans[cntx[i]][cnty[i]];
69         //printf("%d ", B[i].x);
70     }
71     //putchar('\n');
72     dft(A); dft(B);
73     //for(Rint i = 0;i < n;i ++) printf("(%d, %d)\n", A[i].x, A[i].y);
74     //for(Rint i = 0;i < n;i ++) printf("(%d, %d)\n", B[i].x, B[i].y);
75     for(Rint i = 0;i < n;i ++) A[i] = A[i] * kasumi(B[i], t);
76     idft(A);
77     int inv, tmp;
78     exgcd(n, p, inv, tmp);
79     inv = (inv + p) % p;
80     for(Rint i = 0;i < n;i ++)
81         printf("%d\n", (LL) A[i].x * inv % p);
82 }
UOJ272

 

Guess you like

Origin www.cnblogs.com/AThousandMoons/p/10926924.html