首页 > 其他分享 >枚举子集&高维前缀和学习笔记

枚举子集&高维前缀和学习笔记

时间:2023-12-18 17:37:15浏览次数:24  
标签:前缀 二进制 sum state 枚举 子集 高维

枚举子集

首先 \(n\) 位二进制数可以表示一个大小为 \(n\) 的集合的所有子集。接下来的问题均用二进制数展开。

一种暴力的想法是枚举所有数然后判一下是否满足条件,单次时间复杂度 \(O(2^n)\),对所有数做一遍就是 \(O(4^n)\)。

发现有很多枚举是无用的,考虑怎么样让每次枚举出来的都必定是个子集。

对于两个二进制数 \(a,b\),\(a\operatorname{and}b\) 就是 \(a\) 和 \(b\) 的交集。

而将一个二进制数减一会怎么变化?最后一位 \(1\) 变成 \(0\),后面的 \(0\) 全部变成 \(1\)。考虑与上原数,就变成了去掉最低位的 \(1\),将更低位取满。重复这两个操作,相当于每次改变当前最低位的状态,枚举更低位的子集。正确性显然,枚举顺序自然是从大到小。

现在的时间复杂度其实就是子集个数的级别。一个含有 \(i\) 个 \(1\) 的二进制数的子集个数为 \(2^i\),所有二进制数的子集个数加和就是:

\[\sum_{i=0}^n\binom{n}{i}\times 2^i \]

将 \(x=1,y=2\) 代入就等于 \((1+2)^n=3^n\)。

当然也可以通过组合意义来阐释,每个位置要么为 \(1\)(该位一定选)要么为 \(0\)(可以选也可以不选)。

高维前缀和

基本是贺 OI Wiki 的

现在有一个 \(U\) 维空间 \(D\),需要对每个点 \(state\) 计算满足所有维度均小于等于 \(state\) 的点的贡献。

令 \(sum_{i,state}\) 表示后 \(U-i\) 维均与 \(state\) 相同的点的贡献,那么初始化 \(sum_{0,state}\) 为与 \(state\) 相同的点的贡献,最终答案为 \(sum_{U,state}\)。

其递推关系是 \(sum_{i,state}=sum_{i-1,state}+sum_{i,state'}\),其中 \(state'\) 为第 \(i\) 维 \(state\) 的前驱(第 \(i\) 维恰好少 \(1\))。时间复杂度为 \(O(D\times|U|)\),\(|U|\) 其实就是每一维大小的乘积。

如果无法直接理解可以慢慢来,我们从二维入手:一个矩阵。

先按行做一遍前缀和,再对行的前缀数组按列做一遍前缀和。容易发现,点 \((x,y)\) 通过一条特定的路径对点 \((x',y')(x\leq x',y\leq y')\) 产生贡献,这条路径就是:

\[(x,y)\to(x,y+1)\to(x,y+2)\to\cdots\to(x,y')\to(x+1,y')\to(x+2,y')\to\cdots\to(x',y') \]

推广到更高维的情况,一维一维地搞,一步一步地递推,都能得到这样一条特定的路径,所以不重不漏。

实际上就是已经递推过的维小于等于的情况已经算进了已经递推过的维等于的情况。

标签:前缀,二进制,sum,state,枚举,子集,高维
From: https://www.cnblogs.com/landsol/p/17911733.html

相关文章

  • 无涯教程-Java - Enumeration 枚举接口函数
    Enumeration接口定义了可以枚举对象集合中的元素的方法。下表总结了Enumeration声明的方法-Sr.No.Method&Remark1booleanhasMoreElements()当实现时,必须在提取更多元素时返回true,而在列举所有元素时返回false。2ObjectnextElement()这将返回枚举中的下一个对象......
  • 实验6 C语言结构体、枚举应用编程
    task11//P286例8.172//对教材上的程序作了微调整,把输出学生信息单独编写成一个函数模块3//打印不及格学生信息和所有学生信息程分别调用45#include<stdio.h>6#include<string.h>7#defineN3//运行程序输入测试时,可以把这个数组改......
  • 实验6 C语言结构体、枚举应用编程
    1、实验1运行结果2、实验2源代码 1#include<stdio.h>2#include<string.h>3#defineN104#defineM8056typedefstruct{7charname[M];//书名8charauthor[M];//作者9}Book;1011intmain(){12Bookx[N]=......
  • 前缀和,差分,二叉堆
    目录前缀和一维数组前缀和二维数组前缀和差分二叉堆前缀和一维数组前缀和代码如下:for(inti=0;i<n;i++){if(i==0)y[i]=x[i];elsey[i]=y[i-1]+x[i];}或者for(inti=1;i<=n;i++){y[i]=y[i-1]+x[i];}二维数组前缀和代码如下:for(inti=1;i<=n;i++){f......
  • 实验6 C语言结构体、枚举应用编程
    实验任务1源代码:1#include<stdio.h>2#include<string.h>3#defineN10//运行程序输入测试时,可以把这个数组改小一些输入测试45typedefstructstudent{6intid;//学号7charname[20];//姓名8......
  • 十一,JAVA内部类,枚举
    内部类描述事物内部的事物;就是一个类定义在另一个类的内部当内部类定义在成员变量的位置上时,可以被成员修饰符修饰,修饰后会具备修饰符的特征:private:只能在当前类中访问static:访问出现局限性privateintnum=110;  classInner{  ......
  • 拓展了个新业务枚举类型,资损了
    分享是最有效的学习方式。案例背景翻车了,为了cover线上一个业务场景,小猫新增了一个新的枚举类型,盲目自信就没有测试发生产了,由于是底层服务,上层调用导致计算逻辑有误,造成资损。老板很生气,后果很严重。产品提出了一个新的业务场景,新增一种套餐费用的计算方式,由于业务比较着急,......
  • Java第十一课_内部类,Object类,枚举和异常
    1.内部类一般内部类publicclassPratice{publicstaticvoidmain(String[]args){/*内部类:描述事物内部的事物;就是一个类定义在另一个类的内部当内部类定义在成员变量的位置上时,可以被成员修饰符修饰,修饰后会具备修饰......
  • 实验6 c语言结构体,枚举应用编程
    task4源代码1#include<stdio.h>2#include<string.h>3#defineN1045typedefstruct{6charisbn[20];//isbn号7charname[80];//书名8charauthor[80];//作者9doublesales_price;//......
  • Go语言编程教程4-枚举
    课程要点了解Golang中的枚举自定义枚举值跳过某个枚举值枚举的常用惯例了解fmt.Stringer接口Golang中的枚举在Golang中并没有像其他语言一样,拥有类似于enum的常规枚举类型,而是通过使用一组常量来实现类似枚举的功能。如下所示,我们定义了三个常量来表示状态语义的枚举值......