Time Limit: 3000 ms Memory Limit: 256 MB

Description

  IT = Inverse Transform

  两个长度为 \(2^n\) 的序列 \(a,b\). ( 下标从 0 到 \(2n−1\) )

  满足 \(0≤a_i≤10^9\) , 且 \(b\) 由 \(a\) 变换而来, 变换如下:

\[b_i=\sum\limits_{0≤j<2^n}f((i∨j)⊕i) a_j
\]

  其中 \(∨\) 表示按位或, \(⊕\) 表示按位异或. \(的二进制中的个数为偶数f(x)=[x的二进制中1的个数为偶数]\)

  (其中 [expression] 当 expression为真时为 1, 否则为 0)

  现在, \(a\) 序列被玩丢了...

  请你通过 \(b\) 序列还原出 \(a\) 序列

Input

  第一行一个数 \(T\) 表示测试数据组数

  接下来对于每组数据 :

  第一行一个整数 \(n\)

  第二行 \(2^n\) 个整数, 表示序列 \(b\)

Output

  输出包括 \(T\)行

  每行 \(n\) 个整数, 表示序列 \(a\)

Sample Input

4
0
1
1
1 3
2
5 3 4 10
3
101 91 92 104 93 105 108 190

Sample Output

1
1 2
1 2 3 4
31 24 26 23 27 23 24 12

HINT

  对于10% 的数据 \(n≤5\)

  对于另外10%​ 的数据\(n≤10\)

  对于100%​ 的数据 : \(T≤5,1≤n≤20\)

  数据保证 \(b\) 序列 能 唯一地对应一个 \(a\) 序列

  且保证对应的 \(a\) 序列满足 \(0≤a_i≤10^9\)

  ( 注意 : 但 不保证 读入的 \(b\) 序列满足 \(0≤b_i≤10^9\) )


Solution

  • 10%

  这个直接大力高斯消元就好了,注意是。。不保证\(b\)是int所以要用long long。。

(另外10%不会qwq)

  • 100%

  首先观察一下那个诡异的变换\((i∨j)⊕i\)(记作\(change(x,y)\)好了)我们考虑一下把不同的\(0\)和\(1\)组合带进去会得到什么:

\[\begin{aligned}
change(0,1)=1\ \ \ \ \ \ \ \ \ \ \ \ change(1,1)=0\\
change(0,0)=0\ \ \ \ \ \ \ \ \ \ \ \ change(1,0)=0\\
\end{aligned}
\]

  会发现带进去的除了\((0,1)\)以外其他全部都是\(0\)

  然后我们再看一下那个诡异的\(f\)函数,会发现我们需要考虑的只是\(change\)后的\(1\)的个数的奇偶性

  然后因为这个东西每位的运算是独立的,再加上是二进制,可以考虑分治来解决这个问题

  \(b\)推\(a\)比较烦,那么就先看\(a\)推\(b\)

  考虑每次将这个数列分成两半,对于\([l,mid]\)中的\(b_i\),我们只求\(b_i=\sum\limits_{j=l}^{mid}f(change(i,j))a[j]\)

  同理\([mid+1,r]\)中的\(b_i=\sum\limits_{j=mid+1}^{r}f(change(i,j))a[j]\)

  换句话来说,就是对于分成的每一个区间,我们只求这个区间内对答案的贡献,按照这样的方式,分到最后区间长度为\(1\)时,我们可以得到\(b_i=a_i\),然后再将这些分开的区间一层一层地合并,同时统计跨区间的贡献,最后得到完整的\(b\)数组(有点像。。线段树的pushup一样?)

  那么现在考虑怎么统计跨区间的贡献

  我们考虑将\([l,mid]\)和\([mid+1,r]\)合并成\([l,r]\)的情况,考虑这样划分出来的区间的性质,必定是\([2^n,2^m-1]\)这样的形式,记\([l,mid]\)的区间长度为\(2^k\),\([l,mid]\)和\([mid+1,r]\)还满足这两个区间对应的下标写成二进制后,后\(k\)位是一样的,只有第\(k+1\)位不同,举\([0,1]\)和\([2,3]\)为例子,两个区间对应的下标写成二进制后分别是\(00,01\)和\(10,11\),对应起来只有第\(2\)位是不同的,而且左边的一组这位全是\(0\),右边的一组这位全是\(1\)

  清楚了这样的性质之后,再考虑合并区间就方便多了

  

  为了方便我们将\([l,mid]\)记作\(bx\)(下标从\(l\)到\(mid\) ),\([mid+1,r]\)记作\(by\)(下标从\(mid+1\)到\(r\) ),这两个区间合并后在大区间记作\(b\)(下标从\(l\)到\(r\) ),\(b\)由\(b'x\)和\(b'y\)两个部分组成,其中\(b'x\)的下标从\(l\)到\(mid\),\(b'y\)的下标从\(mid+1\)到\(r\)

  首先考虑\(b'y[i]\)是怎么得到的,首先肯定是\(by[i]\)加上\(\sum\limits_{j=l}^{mid}f(change(i,j))a[j]\)得到的,而由于\(bx\)和\(by\)的下标满足上面的性质,所以我们只用考虑不同的那一位对\(1\)的个数的奇偶性的影响

  而因为我们的\(change\)只有带入\((0,1)\)后得到的是\(1\),也就是说只有两个数不同的那一位分别为\(0\)和\(1\)的时候才会对奇偶性有影响,所以我们可以发现,当\(i \in [mid+1,r]\)时,\(\sum\limits_{j=l}^{mid}f(change(i,j))a[j]=bx[i-mid]\)(因为这样不同的两位带进去是\((1,0)\),得出来是\(0\),不会对奇偶性造成影响,而除去不同的那一位,\(i\)和\(i-mid\)的其他位是一样的,贡献相同),所以我们可以知道:

\[b'y[i]=by[i]+bx[i-mid]
\]

  同理,考虑\(b'x[i]\)是怎么得到的,肯定也是\(bx[i]\)加上\(\sum\limits_{j=mid+1}^{r}f(change(i,j))a[j]\)得到的,从同样的角度来分析,会发现\(b'x[i]\)在计算的时候,我们带进去考虑的不同的那位是\((0,1)\),得出来是\(1\),会影响奇偶性,所以那一大段sigma应该是等于计算\(by[i+ mid]\)中\(f\)值为\(0\)的\(a[j]\)的和,我们记\(\sum\limits_{i=mid+1}^{r}a[i]=sum\),那么:

\[b'x[i]=bx[i]+sum-by[i+mid]
\]

  于是乎顺推的问题就很愉快滴解决了(感觉有点像FFT?)

  

​  

  

  但是现在的问题是知道\(b\)来求\(a\)啊,也就是我们要从\(b'x\)和\(b'y\)推回\(bx\)和\(by\) ,所以我们把上面的两条式子稍微变一下:

\[\begin{aligned}
bx[i]&=\frac{b'x[i]+b'y[i+mid]-sum}{2}\\
by[i]&=b'y[i]-bx[i-mid]
\end{aligned}
\]

  看起来不错,但是那个\(sum\)怎么办?

  我们再考虑一下\(by[r]\)(也就是\(by\)部分的最后一位)的值是哪些\(a\)贡献过来的,因为\(r\)是\(2^k-1\)的形式,所以写成二进制之后(不看前导零)都是\(1\),也就是从下面的更小的区间合并上来时,怎么算\(1\)的个数的奇偶性都不会有变化,也就是说\([l,r]\)这个区间内的所有\(a\)都是对其有贡献的,即\(by[r]=\sum\limits_{i=l}^{r}a[i]\),而\(bx[mid]\)(也就是\(bx\)部分的最后一位)则是除了从右边数第\(k\)位是\(0\)外,其他位和\(r\)相同,稍微思考一下其推上来的过程可以发现\(bx[mid]=\sum\limits_{i=l}^{mid}a[i]\)

  那么我们的\(sum=by[r]-bx[mid]\)就好了

  然后就一路推下去长度从\(n\)推到\(1\)就可以将\(a\)完整还原出来啦

  

  

  

  代码大概长这个样子,十分简短

  (题外话:听说这个其实跟FWT很像?然后写起来的循环跟FFT长得一样样的除了最外层逆过来枚举了)

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int MAXN=(1<<20)+10;
ll a[MAXN];
int n,m,T; int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d",&T);
ll sum;
for (int o=1;o<=T;++o){
scanf("%d",&n);
n=1<<n;
for (int i=0;i<n;++i) scanf("%lld",a+i);
for (int len=n;len>=1;len>>=1){
for (int st=0;st<n;st+=len){
sum=a[st+len-1]-a[st+(len>>1)-1];
for (int i=0;i<(len>>1);++i){
a[st+i]=(a[st+i]+a[st+i+(len>>1)]-sum)/2;
a[st+i+(len>>1)]=a[st+i+(len>>1)]-a[st+i];
}
}
}
for (int i=0;i<n;++i)
printf("%lld ",a[i]);
printf("\n");
}
}

IT(然而其实是。。hdu5244?)的更多相关文章

随机推荐

  1. katalon系列十三:5.10新增跳过用例&命令行赋值全局变量

    Katalon Studio升级到5.10版本了,这次新增了2个很实用的功能:一.跳过用例在Listener中新增了跳过用例方法,Listener类似于JUnit4的annotation中的@Befo ...

  2. selenium 结合 docker 构建分布式测试环境 (初学者视角)

    前言:随着自动化测试越学越深,深深觉得有太多的东西需要总结. 1.记录下学习中遇到的坑,当做学习笔记.2.有前人路过看到文章中比较落后的做法,请务必一定要指教.(因为是初学者视角,很多东西只是走通而已 ...

  3. 第七篇 Postman+Node.js+Newman+Jenkins实现自动化测试

    今天终于不咋忙了,学习整理一下一直想做却没实现的事儿,这事已经折磨团队半年之久了.因为项目是B端业务的测试,测试过程中需要生产大量的测试数据,而且都是跨多个系统的测试,对于后置流程的测试,这些同学往往 ...

  4. 《图解 HTTP 》阅读 —— 第五章

    第5章 与HTTP协作的web服务器 一台服务器可以托管多个域名. 在相同的IP地址下,虚拟主机可以寄存多个不同主机名和域名的网站,所以在发送HTTP请求时,必须在Host首部内指定完整的主机名和域名 ...

  5. python购物车优化

    一.需求分析 拥有用户接口和商家接口 用户能够进行消费记录查询,充值,购物等功能,消费记录存储于数据库 商家可以进行商品的增删改等操作 二.程序流程图 程序大致流程图如下: 三.代码实现 本程序分成两 ...

  6. Hyperledger Fabric CouchDB as the State Database——使用CouchDB

    使用CouchDB作为状态数据库 状态数据库选项 状态数据库包括LevelDB和CouchDB.LevelDB是嵌入在peer进程中的默认键/值状态数据库,CouchDB是一个可选的外部状态数据库.与 ...

  7. 01_基于TCP的循环为同一个客户端下载文件的下载器

    原版: TCP分为客户端(client)和服务器(server),每次服务器只能为客户端提供一次的下载服务. 改良版: TCP分为客户端(client)和服务器(server), (1)每次服务器能为 ...

  8. Chrome 鲜为人知的秘籍(内部协议)&&Chrome功能指令大全

    楼主以 Chrome 版本 39.0.2171.95 m 为例,耗费2小时的记录: chrome://accessibility 用于查看浏览器当前访问的标签,打开全局访问模式可以查看:各个标签页面的 ...

  9. javascript提高篇

    本章简介 本章内容比较少,有三个分享的知识.你可能都看过了,因为网上也有很多提问和解答,如果没看过或者没搞懂,你可以再看看这篇文章. 1. 数组去重方法的演变    --  走向代码缩短化 2. [] ...

  10. 上午做的第一个安卓app

    刚开始学习安卓开发,有好多不懂,好多快捷键不知道,好多文件也不知道是干什么用的,初学时的确会有很多烦恼,比如哪里又多一个空格也会报错,有时候错误很难看懂. 嘿嘿,一上午的功夫边学习边调代码,做出了我第 ...