首页 > 其他分享 >高维前缀和

高维前缀和

时间:2024-10-17 22:21:14浏览次数:5  
标签:前缀 11111 11101 11011 贡献 枚举 子集 高维

1原来我不会。

子集枚举

枚举一个集合的每个子集的所有子集。

for(int s=0;s<(1<<n);s++){
    for(int s0=s;;s0=s0&(s0-1)){
        cout<<s0<<' ';
    }
}

其中 \(s0\) 即为枚举的每个子集的所有子集。

这是为什么?

第一层循环中,我们枚举了一个子集。

那么第二层循环中,我们就要枚举这个子集的所有子集。

从 \(s\) 本身开始,从大往小降序枚举。

我们想快速从一个子集跳转到比它小的第一个子集。

分类讨论一下:

若当前的子集最低位为 \(1\),比它小的第一个子集显然是它 \(-1\)。

否则,当前子集最低位为 \(0\),考虑 \(-1\) 以后会发生什么变化。

发现,会将第一段后缀 \(10000000……\) 变成 \(011111111……\),也就是让最低位的 \(1\) 变成了 \(0\),最低位之前的 \(0\) 都变成了 \(1\)。

此时只需保留原集合中的所有位置即可,所以 \(\&s\) 就行了。

发现我们的枚举不重不漏,那么复杂度就是所有子集的子集个数的和。

即 \(\sum_{i=0}^{n}C_{n}^{i}2^i=3^n\)。

高维前缀和

对于原集合的每一个子集,都有一个初始权值,现在求每一个子集的子集权值和。

for(int i=1;i<=n;i++){
    for(int j=0;j<(1<<n);j++){
        if(s&(1<<(i-1))) f[s]+=f[s^(1<<(i-1))];
    }
}

这该如何理解?

考虑一位一位地加入贡献。

或者说,每次枚举时都将高位的位置钦定好,只考虑低位位置子集所带来的贡献。

这么说太抽象了,举个例子吧。

假设当前枚举到了第 \(2\) 位,要贡献到 \(11111\) 。

那么我们就让当前的 \(11101\) 对它贡献。

此时,高位的三位是不变的,而 \(11101\) 已经是一个前三位不变,后两位是子集和的东西了。

即 \(11101\) 此时已经是 \(11100\) 与 \(11101\) 的和了。

那么就可以直接让它贡献到 \(11111\) 了。

当枚举到第三位时,我们钦定的就是高位的两位不变了。

对于 \(11111\) ,现在我们让 \(11011\) 贡献到它。

此时,\(11011\) 也是钦定了前两位,后两位的子集和了。

即 \(11011\) 此时是原来的 \(11000,11001,11010,11011\) 的和了。

那么也可以让它贡献到 \(11111\) 了。

类似的考虑问题即可。

标签:前缀,11111,11101,11011,贡献,枚举,子集,高维
From: https://www.cnblogs.com/hugoi/p/18473200

相关文章

  • Codeforces Round 924 (Div. 2) D. Lonely Mountain Dungeons(推式子,思维,差分,前缀和)
    题目链接CodeforcesRound924(Div.2)D.LonelyMountainDungeons思路令f(n,m......
  • 前缀和和差分归纳总结
    前缀和数组可以在O(1)的时间内求得某一区间中的所有数据的和差分数组可以在O(1)的时间内对某一区间中的所有数据进行加减操作原数组求差分及为差分数组,差分数组再求前缀和即为原数组一维前缀和:设原数组为a[N],前缀和数组为s[N],数组下标都从1开始存储每个s[i]等于a[1]......
  • 洛谷题单指南-字符串-P1470 [USACO2.3] 最长前缀 Longest Prefix
    原题链接:https://www.luogu.com.cn/problem/P1470题意解读:求s最长前缀长度,使得可以拆解成p集合中的字符串解题思路:动态规划:设s字符串下标从1开始,p集合用set<string>保存所有的元素状态表示:设f[i]表示前i个字符s[0~i-1]是否能拆解成p中的元素状态计算:对于j=i-1开始往后倒......
  • 三维前缀和
    二维前缀和模板:预处理:dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+map[i][j];查询:dp[x2][y2]+dp[x1-1][y1-1]-dp[x1-1][y2]-dp[x2][y1-1]三维前缀和模板:预处理:pre[i][j][k]=mp[i][j][k]-pre[i-1][j-1][k]-pre[i-1][j][k-1]-pre[i][j-1][k-1]+pre[i][j][k-1]+pre[i][j-1][......
  • 每日OJ题_牛客_比那名居的桃子_滑动窗口/前缀和_C++_Java
    目录牛客_比那名居的桃子_滑动窗口/前缀和题目解析C++代码Java代码牛客_比那名居的桃子_滑动窗口/前缀和比那名居的桃子(nowcoder.com)描述:        小红有一天看到了一只桃子,由于桃子看上去就很好吃,小红很想把它吃掉。已知吃下桃子后,每天可以获得ai​的......
  • 前缀和笔记
    前缀和笔记对于一个一维数组a[m]其前i项和记作s[i]如果想要对a[m]中任意连续段的值进行求和,例如a[l]~a[r]则可使用前缀和数组进行o(n)计算inta[m],s[m];s[0]=0;//定义s[0]的值,防止边界问题for(inti=0;i<m;i++){ cin>>a[i]; s[i]=s[i-1]+a[i];}这样的话,s......
  • Python数据分析NumPy和pandas(五、NumPy高维数组的数学计算 2)
    一、Numpy的花式索引FancyIndexing花式索引FancyIndexing是NumPy采用的一个术语,用于描述使用整数数组进行索引。1.举例:用元组来创建一个8x4的二维数组zeros,并循环赋值:importnumpyasnparr=np.zeros((8,4))#为二维数组arr每行赋值foriinrange(8):arr[i......
  • 二维前缀和 & 二维差分
    二维前缀和求二维前缀和后,能够实现\(O(1)\)求原数组二维区间和,但是不支持修改。lln,m,sum2[N][N],c[N][N];voidSum2_pre(){fr(i,1,n)fr(j,1,m)sum2[i][j]=sum2[i-1][j]+sum2[i][j-1]-sum2[i-1][j-1]+c[i][j];}llSum2(llx......
  • ARC136C Circular Addition [高维前缀和]
    Description给定一个长度为\(n\)的正整数序列\(A\),求有多少对\((i,j)\)使得\(A_i+A_j\)不发生进位操作。\(A_i<10^6\)。Solution显然对于每个\(A_i\),设\(B_i=999999-A_i\),那么\(A_i\)可以和所有位上的数都小于等于\(B_i\)对应位上的数的数匹配,考虑用桶加前缀......
  • 算法修炼之路之前缀和
    目录一:一维前缀和二:二维前缀和 三:LeetCodeOJ练习  1.第一题2.第二题 3.第三题 4.第四题5.第五题6.第六题一:一维前缀和这里通过例题来引出牛客_DP34【模板】前缀和画图分析:具体代码:#include<iostream>#include<vector>usingnamespacestd;int......