幻想的狼与旅行从者
Description
现在灰狼与蔷薇请你写一个程序,来解压一个被一种简单的jsoi压缩技术压缩过的一串信号(一列数)。考虑我们有一列包含偶数个数字的数列,将其分成n/2组,计算出每组两个数的和与差,分别写成两列长度为原来一半的。以同样的方式对变换后的信号的前半段(即以s(i)为输入信号)作变换,如此循环,直到输入信号的长度为1为止。你可以假定输入信号的长度一定是 2n,并且每个数字信号的范围都在 0~255之间。
Analysis
非常明显的分治算法,理解题意后进行倒推。长度为1无须倒推。长度为2的序列中第一个数字为两数之和,第二个数字为两数之差。利用基本的数学知识就可以算出两个数原本的值然后放回原位,问题退回到倒数第二次操作,第一个数字对应第三个,第二个对应第四个,以此类推,不断还原,直到还原log2n次操作,则为明文。
Code
#include <bits/stdc++.h>
int n,num[257],load[257];
int main(){
freopen("wavelet.in","r",stdin);
freopen("wavelet.out","w",stdout);
while(1){
scanf("%d",&n);
if(!n)break;
memset(num,0,sizeof(num));
memset(load,0,sizeof(load));
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=log2(n);i++){
for(int j=1;j<=(1<<i-1);j++){
int x=num[j];
int y=num[j+(1<<i-1)];
load[j*2]=(x-y)/2;
load[j*2-1]=load[j*2]+y;
}
for(int j=1;j<=(1<<i);j++)
num[j]=load[j];
}
for(int i=1;i<=n;i++)
printf("%d ",num[i]);
printf("\n");
}
return 0;
}