CSU1977: Bit-reversal Permutation
Description
A fast Fourier transform (FFT) algorithm computes the discrete Fourier transform (DFT) of a sequence, or its inverse (IFFT). Fourier analysis converts a signal from its original domain (often time or space) to a representation in the frequency domain and vice versa. An FFT rapidly computes such transformations by factorizing the DFT matrix into a product of sparse (mostly zero) factors. As a result, it manages to reduce the complexity of computing the DFT from O(n2), which arises if one simply applies the definition of DFT, to O(nlogn), where n is the data size.
——From Wikipedia
During this summer holiday, csuxushu feels so bored to learn FFT. Because FFT is a complicated algorithm, he need to apply a bit-reversal permutation to a sequence first before DFT which is a part of FFT.
In applied mathematics, a bit-reversal permutation is a permutation of a sequence of n items, where n = 2^k is a power of two. It is defined by indexing the elements of the sequence by the numbers from 0 to n − 1 and then reversing the binary representations of each of these numbers (padded so that each of these binary numbers has length exactly k). Each item is then mapped to the new position given by this reversed value.
Because all fellows in CSU(California State University ) can apply FFT, NTT or even FWT, it is a shame that he even doesn't know how to take the first step. As one of the best computer programmer in CSU, can you help him?
You may think this problem is too hard to solve. In fact, it is a piece of cake to you. Remember to see the hint :-)
Input
The first line of the input gives the number of test cases T(T≤10); T test cases follow.Each test case contains a number sequence.
In each case, the first line is a number N(1≤N≤10^5), the number of elements in the following sequence.The second line is the sequence.Its length may not be exactly a power of two, so you can append some zeros to make it the minimal power of two larger than or equal to N.
Output
For each test case, output the sequence from input in bit-reversal order.
Sample Input
1
6
21 58 96 12 45 65
Sample Output
21 45 96 0 58 65 12 0
Hint
Bit-reverse Order
中文提示:可以看到,我們最終處理的係數從左至右的編號的二進制形式分別爲000,100,010,110,001,101,011,111,若將其二進制反序,可得000,001,010,011,100,101,110,111,這些反序的二進制編碼是從小到大排列的。也就是說,我們可以按照每個下標的二進制編碼來確定處理係數的順序。這種方法就稱爲位逆序置換(Bit-reversal permutation)。
Source
2017年8月月賽
Author
徐戍
比賽中將問題想複雜了,好久也沒搞出來。實際上直接按照先0後1的次序,遞歸地生成順序序列的二進制數碼,同時逆序地計算出這些數碼對應的十進制數,直接取出數組中元素就行了。比如我們生成的是
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5+10;
int sample[maxn*10];
int T, n, k;
void dfs(int kk, int index){
if(kk == 0){ // 已產生k位二進制數,並已經知道了它們逆序後對應的十進制數。
if(index == (1<<k)-1) // 不論如何做位逆序置換,最後一個輸出的一定是二進制全爲1的數。輸出它後換行。
printf("%d\n", sample[index]);
else // 否則輸出後空格。
printf("%d ", sample[index]);
return;
}
dfs(kk-1, index+0); // 遞歸調用的同時進行逆序進制轉換。
dfs(kk-1, index+(1<<(k-kk)));
}
int main(){
#ifdef TEST
freopen("test.txt", "r", stdin);
#endif // TEST
cin >> T;
while(T--){
memset(sample, 0, sizeof(sample));
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &sample[i]);
}
k = 0;
while(1<<k < n) k++; // 求出令2^k不小於n的最小k值。
dfs(k, 0);
}
return 0;
}
/**********************************************************************
Problem: 1977
User: xyJiang
Language: C++
Result: AC
Time:400 ms
Memory:5924 kb
**********************************************************************/