「CF1713F」 Lost Array 题解
「CF1713F」 Lost Array 题解
题意
\(~~~~\) 有一个长为 \(n\) 的数组 \(\{a\}\) ,把它作为方阵 \(b\) 的第零层,从第一层开始 \(b_{i,j}=b_{i-1,j} \oplus b_{i,j-1}\) ,直到第 \(n\) 层。现在已知每一层的最后一个位置,求构造 \(\{a\}\) 来还原它或说明无解。
\(~~~~\) \(1\leq n\leq 5\times 10^5\)。
题解
\(~~~~\) 什么神仙题!!!!!1
\(~~~~\) 先由 \(\text{CF}\) 第?定律得知没有样例无解所以大概率没有无解的情况。
\(~~~~\) 那就考虑用 \(\{a\}\) 怎么构造 \(\{b\}\) 。下面是一个非常妙的转化。
\(~~~~\) 先考虑把 \(a\) 从右往左编号为 \(0,1,\dots,n-1\) 。先考虑 \(a_i\) 对 \(b_{j,j}\) 的贡献(矩阵的行也反过来编号,但列还是从上到下编号)那就是 \(\binom{i-j+j}{j}=\binom{i}{j}\) ,由于是异或,所以我们只关心 \(\binom{i}{j} \bmod 2\) 的值。由于结论:\(\binom{i}{j}\) 为奇数当且仅当 \(i \text{and} j=j\) ,其中 \(\text{and}\) 指按位与,那么我们可以发现 \(b_{j,j}\) 其实就是 \(a\) 这里的异或超集和。结论的证明有心情再来补吧。
\(~~~~\) 同理从 \(b_{i,i}\) 走到 \(b_{0,j}\) (列上还是从上到下顺序编号)的方案数为 \(\binom{j}{i}\) ,所以 \(b_{0,j}\) 是 \(b_{i,i}\) 的子集和。
\(~~~~\) 那现在我们已经知道了 \(b_{0,j}\) ,所以用逆子集和和逆超集和(在异或意义下也就是子集和和超集和)来还原 \(a\) 即可。
代码
查看代码
#include <bits/stdc++.h>
using namespace std;
template<typename T>void read(T &x)
{
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x*=f;
}
int arr[1000005];
int main() {
#ifndef ONLINE_JUDGE
freopen("input","r",stdin);
freopen("output","w",stdout);
#endif
int n;read(n);n--;
for(int i=0;i<=n;i++) read(arr[i]);
int Lg=log2(n);
for(int i=0;i<=Lg;i++) for(int j=n;j>=0;j--) if((j>>i)&1) arr[j]^=arr[j^(1<<i)];
for(int i=0;i<=Lg;i++) for(int j=0;j<=n;j++) if(!((j>>i)&1)) arr[j]^=arr[j^(1<<i)];
for(int i=n;i>=0;i--) printf("%d ",arr[i]);
return 0;
}
/*
清夜无尘。月色如银。酒斟时、须满十分。浮名浮利,虚苦劳神。叹隙中驹,石中火,梦中身。
虽抱文章,开口谁亲。且陶陶、乐尽天真。几时归去,作个闲人。对一张琴,一壶酒,一溪云。
*/