ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ARC137-D 报灵智慧壬

2022-04-30 17:31:27  阅读:189  来源: 互联网

标签:ARC137 times2 dbinom text sum 智慧 报灵 zeta Mx


l1nk

editorial


  • 题意:

给定序列 \(\{a_n\}\) ,求出 \(a_n\) 在 \(k \in [1,m]\) 次前缀异或和后的值.

  • 分析:

一个显然的事情是我会且仅会打暴力(?

赛后 \(\text{dottle}\) 过来讲题
发现它又考了一次 \(\zeta\) 变换

草, 我果然还是不会做

因为异或和加法非常像所以我们把它当成加法处理
那么就是快速求得 \(a_i\) 在 \(k\) 次前缀和中对 \(a_n\) 的贡献

这个问题实质上等价于
若在位置 \(i\) 时可以走到 \([i,n]\) 的任意位置,要用 \(k\) 步从 \(i\) 走到 \(n\) 的所有路径

这个问题实质上也就是
有 \(m\) 个无标号球,放进 \(n\) 个盒子的方案数

为了便于插板每个盒子先放一个
那么答案就是 \(\dbinom{n+m-1}{n-1}\)
所以对于 \(a_i\) ,当 \(f_i=\dbinom{n-i+k}{n-i} \mod 2 =1\) 时,对 \(a_n\) 有一次贡献

然后有一个性质:
若 \(\dbinom{n}{m} \mod 2=1\) ,当且仅当 \(n\&m=m\)

在网上搜到了一个证明,orz
但是他的 \(\LaTeX\) 好像炸了(
所以我再写一遍

证明:

\[\dbinom{n}{m}=\frac{n!}{m!(n-m)!} \]

设 \(n!\) , \(m!\) , \((n-m)!\) 分解质因数后 \(2\) 的个数为 \(A\) , \(B\) , \(C\)
显然若 \(\dbinom{n}{m} \mod 2=1\) 那么一定有 \(A=B+C\)
又有性质:

\[f(p,n)=\sum_{i=1}^{\infty} \lfloor \frac{n}{p^i} \rfloor \]

其中 \(f(p,n)\) 表示 \(n!\) 质因数分解中 \(p\) 的个数, \(p \in Prime\)
结合 \(n\) 的二进制表示

\[bit(n)=\sum_{i=1}^{k}a_i\times2^{i-1} \]

那么

\[f(2,n)=\sum_{i=1}^{k}\lfloor \frac{\sum_{j=1}^{k}a_j\times2^{j-1}}{2^i} \rfloor \]

其中 \(k\) 为 \(bit(n)\) 的位数
所以

\[f(2,n)=\sum_{i=1}^{k}\frac{\sum_{j=i+1}^{k}a_j\times2^{j-1}}{2^i} \]

(关于这一步的舍入在后文有证明)
写得更好看就是

\[f(2,n)=\sum_{i=1}^{k}\sum_{j=i+1}^{k}a_j\times2^{j-i-1} \]

\[=\sum_{j=1}^{k}a_j\sum_{i=0}^{j-2}2^i \]

\[=\sum_{j=1}^{k}a_j(2^{j-1}-1) \]

\[=(\sum_{j=1}^{k}a_j\times2^{j-1})-(\sum_{j=1}^{k}a_j) \]

\[=n-\sum_{j=1}^{k}a_j \]

\[=n-\text{popcount}(n) \]

\[f(2,n)=n-\text{popcount}(n) \]

再设 \(n\) , \(m\) , \((n-m)\) 的 \(\text{popcount}\) 为 \(a\) , \(b\) , \(c\)
那么

\[n-a=(m-b)+(n-m-c) \]

\[n-a=n-(b+c) \]

也就是说

\[a=b+c \]

观察可以发现当且仅当 \(bit(m) \subseteq bit(n)\)
也就是说 \(n\&m=m\)

\(\text{Q.E.D.}\)

证明了这个性质后,我们把贡献还原回异或,发现一个 \(a_i\) 在第 \(k\) 轮对 \(a_n\) 产生一次 \(\text{XOR}\) 贡献当且仅当

\[\dbinom{n-i+k}{n-i}\mod2=1 \]

那么就有

\[(n-i+k)\&(n-i)=(n-i) \]

因为这个柿子又等价于

\[k\&(n-i)=0 \]

所以

\[\complement_{u}(k)\&(n-i)=(n-i) \]

据此, \(\text{dottle}\) 使用了总复杂度为 \(O(m3^{k})\) 枚举 \(\complement_{u}(k)=Mx-k\) 的子集的写法:

for(ri k=0;k<=m-1;++k){
    ri ans=a[n];
    for(ri id=Mx-k;id;id=(id-1)&(Mx-k)) //枚举下标中为Cu(k)子集的部分 
    if(id<=n) ans^=a[n-id];
    writesp(ans);
}

虽然能过,但是获得了 \(3073ms\) 的优异成绩(

看着std的 \(177ms\) 我茫然失措......

然后发现这个东西其实就是对 \(Mx-k\) 求子集函数和

欸那不就 \(\text{Fast Zeta Transform}\) 了吗???

我们对全集 \(Mx\) 做一次 \(\zeta\) 变换.
具体地,我们把 \(zeta[n-i]\) 初值设置为 \(a[i]\)
求一次正常的快速zeta变换
最后在全集中找到每个 \(zeta[Mx-k]\)
此时它们已经被全部计算完毕,所以直接输出即可

ri Mx=1,t=max(n,m),p0wer=0;
while(Mx-1<=t) Mx<<=1,++p0wer;
--Mx,--p0wer;
vector<int> zeta(Mx); 
for(ri j=1;j<=n;++j)
zeta[n-j]=a[j];
for(ri i=0;i<=p0wer;++i)
for(ri bits=0;bits<=Mx;++bits)
if(bits&(1<<i)) zeta[bits]^=zeta[bits^(1<<i)];
for(ri k=0;k<=m-1;++k)
writesp(zeta[Mx-k]);

为什么可以一次计算完毕呢?
因为我们进行全集的zeta变换时,同时也计算了所有子集的zeta变换

那么最终我们的算法复杂度就是 \(O(n+k2^k) \to O(n+MlogM)\) ,其中 \(M=max\{n,m\}\)

最后跑出了 \(114ms\) .


附:对证明过程中去掉下取整步骤的小学生证明

舍掉的部分为

\[\sum_{j=1}^{i}a_j2^{j-1-i} \le \sum_{j=1}^{i}2^{j-1-i}=2^{-i}\sum_{j=1}^{i}2^{j-1} \]

由小学的等比数列知识可知

\[\text{RHS}=2^{-i}\times2^0\times(2^i-1)=1-2^{-i} \lt 1 \]

所以它们和下取整一起去掉是正确的

\(\text{Q.E.D.}\) (雾

标签:ARC137,times2,dbinom,text,sum,智慧,报灵,zeta,Mx
来源: https://www.cnblogs.com/suitlie/p/16210754.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有