Codeforces 772D - Varying Kibibits(高维差分+二项式定理维护 k 次方和)
首先很容易注意到一件事,那就是对于所有 \(f(S)\) 可能成为 \(x\) 的集合 \(S\),必定有 \(\forall y\in S\),\(x\) 的每一位都 \(\le y\) 的对应位,于是我们考虑设 \(h(x)\) 表示所有满足 \(x\) 的对应位都小于 \(f(S)\) 的对应位的 \(S\) 的贡献之和,显然我们求出 \(h(x)\) 之后,可以把 \(0\sim 999999\) 中的数都看作一个拥有六个维度,每个维度中的数都 \(\in[0,9]\) 的元素,然后仿照二进制下的高维差分跑一遍高维差分即可。
接下来考虑怎样求出 \(h(x)\),下记 \([x\subseteq y]\) 表示 \(x\) 是否每一位都 \(\le y\) 的对应位,那显然根据之前的定义有 \(h(x)=\sum\limits_{S\subseteq T}[\forall y\in S,x\subseteq y](\sum\limits_{y\in S}y)^2\),这里面带个平方,可能不是特别显然,我们考虑一个简单些的问题,那就是假设每个集合 \(S\) 的贡献都是 \(1\) 而不是 \((\sum\limits_{y\in S}y)^2\),那我们只需求出 \(c(x)=\sum\limits_{y\in T}[x\subseteq y]\),那么显然就有 \(h(x)=2^{c(x)}\)。回到原题,注意到我们高维前缀和的实质是合并两个集合 \(S,T\) 的贡献,也就是倘若我们已经知道了 \(S\) 的贡献和 \(T\) 的贡献,怎样支持快速求出 \(S\cup T\) 的贡献。我们如果记 \(st(x)=\{y|y\in T,x\subseteq y\}\),那么 \(h(x)=\sum\limits_{S\subset st(x)}(\sum\limits_{y\in S}y)^2\)。并且此题还带个平方,做过 P6144 [USACO20FEB]Help Yourself P 的同学应该都知道,碰到这类高次方求和的问题,我们都可用二项式定理将其拆成若干个低次方的和,然后将它们一一合并即可。具体来说,根据二项式定理初一课内有 \((x+y)^2=x^2+2xy+y^2\),故我们对于每个集合 \(S\) 维护零次方和、一次方和和二次方和,即 \(S_0=\sum\limits_{S'\subseteq S}1,S_1=\sum\limits_{S'\subseteq S}\sum\limits_{x\in S'}x,S_2=\sum\limits_{S'\subseteq S}(\sum\limits_{x\in S'}x)^2\),那么当合并两个集合 \(S,T\) 时,就有:
- \((S\cup T)_0=\sum\limits_{U\subseteq(S\cup T)}1=\sum\limits_{U\subseteq S,V\subseteq T}1=\sum\limits_{U\subseteq S}\sum\limits_{V\subseteq T}1=S_0T_0\)
- \[\begin{aligned}(S\cup T)_1&=\sum\limits_{U\subseteq(S\cup T)}\sum\limits_{x\in U}x=\sum\limits_{U\subseteq S,V\subseteq T}(\sum\limits_{x\in U}x+\sum\limits_{x\in V}x)\\&=\sum\limits_{U\subseteq S}\sum\limits_{V\subseteq T}(\sum\limits_{x\in U}x+\sum\limits_{x\in V}x)\\&=\sum\limits_{U\subseteq S}\sum\limits_{x\in U}x·\sum\limits_{V\subseteq T}1+\sum\limits_{V\subseteq T}\sum\limits_{x\in V}x·\sum\limits_{U\subseteq S}1\\&=S_1T_0+S_0T_0\end{aligned}
\] - \[\begin{aligned}(S\cup T)_2&=\sum\limits_{U\subseteq(S\cup T)}(\sum\limits_{x\in U}x)^2=\sum\limits_{U\subseteq S,V\subseteq T}(\sum\limits_{x\in U}x+\sum\limits_{x\in V}x)^2\\&=\sum\limits_{U\subseteq S}\sum\limits_{V\subseteq T}((\sum\limits_{x\in U}x)^2+(\sum\limits_{x\in V}x)^2+2\sum\limits_{x\in U}x\sum\limits_{x\in V}x)\\&=\sum\limits_{U\subseteq S}(\sum\limits_{x\in U}x)^2·\sum\limits_{V\subseteq T}1+\sum\limits_{V\subseteq T}(\sum\limits_{x\in V}x)^2·\sum\limits_{U\subseteq S}1+2\sum\limits_{U\subseteq S}\sum\limits_{x\in U}x·\sum\limits_{V\subseteq T}\sum\limits_{x\in V}x\\&=S_2T_0+S_0T_2+2S_1T_1\end{aligned}
\]
高维前缀和维护下即可,最好开个结构体,时间复杂度 \(6\times 999999\)。
老缝合怪了
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e6;
const int MOD=1e9+7;
int n,pw[MAXN+5],ret[MAXN+5];
struct data{
int sum0,sum1,sum2;
data(){sum0=sum1=sum2=0;}
data(int x){sum0=1;sum1=x;sum2=1ll*x*x%MOD;}
data(int _sum0,int _sum1,int _sum2):sum0(_sum0),sum1(_sum1),sum2(_sum2){}
data operator +(const data &rhs){
return data(
sum0+rhs.sum0,
(1ll*sum1*pw[rhs.sum0]+1ll*pw[sum0]*rhs.sum1)%MOD,
(1ll*sum2*pw[rhs.sum0]%MOD+2ll*sum1*rhs.sum1+1ll*pw[sum0]*rhs.sum2)%MOD);
}
} f[MAXN+5];
int main(){
scanf("%d",&n);pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=2ll*pw[i-1]%MOD;
for(int i=1,x;i<=n;i++) scanf("%d",&x),f[x]=f[x]+data(x);
int cur=1;
for(int i=0;i<=5;i++){
for(int j=MAXN-1;~j;j--){
if((j/cur)%10!=9) f[j]=f[j]+f[j+cur];
}
cur=cur*10;
}
for(int i=0;i<MAXN;i++) ret[i]=f[i].sum2;
cur=1;
for(int i=0;i<=5;i++){
for(int j=0;j<MAXN;j++){
if((j/cur)%10!=9) ret[j]=(ret[j]-ret[j+cur]+MOD)%MOD;
}
cur=cur*10;
} ll ans=0;
for(int j=0;j<MAXN;j++) ans^=1ll*j*ret[j];
printf("%lld\n",ans);
return 0;
}
Codeforces 772D - Varying Kibibits(高维差分+二项式定理维护 k 次方和)的更多相关文章
- 【CF772D】Varying Kibibits FWT
[CF772D]Varying Kibibits 题意:定义函数f(a,b,c...)表示将a,b,c..的10进制下的每一位拆开,分别取最小值组成的数.如f(123,321)=121,f(530, ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- Educational Codeforces Round 61 C 枚举 + 差分前缀和
https://codeforces.com/contest/1132/problem/C 枚举 + 差分前缀和 题意 有一段[1,n]的线段,有q个区间,选择其中q-2个区间,使得覆盖线段上的点最多 ...
- Codeforces Gym 100015G Guessing Game 差分约束
Guessing Game 题目连接: http://codeforces.com/gym/100015/attachments Description Jaehyun has two lists o ...
- Codeforces GYM 100114 D. Selection 线段树维护DP
D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...
- [Codeforces]817F. MEX Queries 离散化+线段树维护
[Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...
- CodeForces 408E Curious Array(组合数学+差分)
You've got an array consisting of n integers: a[1], a[2], ..., a[n]. Moreover, there are m queries, ...
- Codeforces Global Round 2 D 差分 + 前缀和 + 二分
https://codeforces.com/contest/1119/problem/D 题意 有n个数组,每个数组大小为\(10^{18}+1\)且为等差数列,给出n个数组的\(s[i]\),q次 ...
- CodeForces 675C Money Transfers(贪心+奥义维护)
题意:n个银行. 其中存款有+有-. 总和为0. n个银行两两相邻((1,n),(1,2)...(n-1,n)); 问最少移动几次(只能相邻移动)能把所有数变为0. 分析:思路很简单,起始答案算它为n ...
随机推荐
- TypeError: Restaurant() takes no arguments
1. 错误描述 TypeError: Restaurant() takes no arguments 2. 原因:在编写__init__时,pycharm会自动添加关键字,有时会直接写称整型int, ...
- 40个Python入门小程序
有不少同学学完Python后仍然很难将其灵活运用.我整理 37 个Python入门的小程序.在实践中应用Python会有事半功倍的效果. 分享 Github 项目,里面收集了 Python 学习资料 ...
- Java正则中"\\\\"表示普通反斜杠
Java中"\"用于转义字符,"\\"表示普通无转义功能的反斜杠. 如果将字符串当做正则表达式来解析,那么"\\"也有了特殊意义,它与其后的 ...
- ruby基本图片上传
图片上传问题 在我们的项目里,需要实现海报的图片上传,便于更好地向外界展示一个社团活动的基本内容,但是在处理中间件相关问题时遇到了一点小小的挫折.不过这并不要紧,OSS对象存储服务固然好,但是本着交完 ...
- Linux C语言链表你学会了吗?
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用.链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节 ...
- 单片机stm32串口分析
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...
- 常用Java API:Math类
求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double a, doubleb) Math.min(long ...
- SkyWalking配上告警更优秀
前言 对于监控系统来说,不可能让人一直盯着监控看板,而更多的是以自动提醒的方式,比如邮件.短信或微信推送等,当达到或超出预设的告警指标时,就自动发送消息提醒,下面就来说说如何配置SkyWalking的 ...
- 小白自制Linux开发板 十. NES游戏玩起来
本篇基于我们制作的Debian文件系统而展开,而且我们这会玩一些高级的操作方式--用我们的小电脑进行程序编译. 所以本篇操作全部都在我们个的开发板上完成. 1. 开发环境搭建 首先安装gcc, ...
- linux tr
转载:tr命令_Linux tr 命令用法详解:将字符进行替换压缩和删除 (linuxde.net) tr命令 文件过滤分割与合并 tr命令可以对来自标准输入的字符进行替换.压缩和删除.它可以将一组字 ...