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

高维前缀和 (SOSDP)

时间:2023-10-04 15:15:19浏览次数:33  
标签:ch 前缀 int SOSDP while 高维 getchar

介绍

一维前缀和 : $ s[i] = s[i - 1] + a[i] $
二维前缀和: $s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] $

当然也可以这么写:

for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        a[i][j] += a[i - 1][j];
for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        a[i][j] += a[i][j - 1];

\(n\) 维前缀和, 我们可以做 \(n\) 次一维前缀和,差不多这个样子, 跟二维前缀和是类似的。

for(int i[1] = 1; i[1] <= n; i[1]++)
    for(int i[2] = 1; i[2] <= n; i[2]++)
        //...
        a[i[1]][i[2]][i[3]] ... += a[i[1] - 1] ...;
for(int i[1] = 1; i[1] <= n; i[1]++)
    for(int i[2] = 1; i[2] <= n; i[2]++)
        //...
        a[i[1]][i[2]][i[3]] ... += a[i[1]][i[2] - 1] ...;
...

例题

Ⅰ. P5495 Dirichlet 前缀和

根据唯一分解定理,将每个素数看成一维,然后相当于是子集和,用高维前缀和即可。状态压缩,可以仔细思考。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e7 + 67;
int read(){
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -f; ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return x * f;
}
#define uint unsigned int
uint seed;
inline uint getnext(){
	seed ^= seed << 13;
	seed ^= seed >> 17;
	seed ^= seed << 5;
	return seed;
}

bool _u;

int n;
uint b[N], ans;
bool ispri[N];

bool _v;

int main(){
	cerr << abs(&_u - &_v) << " MB\n";
	
	n = read(), seed = read();
	for(int i = 1; i <= n; ++i) b[i] = getnext();
	ispri[1] = 1;
	for(int i = 1; i <= n; ++i){
		if(!ispri[i])
			for(int j = i; j <= n; j += i)
				b[j] += b[j / i], ispri[j] = 1;
		ans ^= b[i];
	}
	printf("%lld\n", ans);
	return 0;
}

Ⅱ. [ARC100E] Or Plus Max

将题目转成对于每个 \(K\) 求 \(i | j = K\) 的最大值,然后就是求子集前缀最大值。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N = (1 << 19) + 67;
int read(){
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -f; ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return x * f;
}

bool _u;

int n;
ll ans;
struct node{
	ll x, y;
	node operator + (const node &p){
		node z;
		if(x > p.x) z.x = x, z.y = max(y, p.x);
		else z.x = p.x, z.y = max(x, p.y);
		return z; 
	}
}a[N];

bool _v;

int main(){
	cerr << abs(&_u - &_v) / 1048576.0 << " MB\n";
	
	n = read();
	for(int i = 0; i < (1 << n); ++i) a[i].x = read(), a[i].y = -1e18;
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < (1 << n); ++j)
			if(j & (1 << i)) a[j] = a[j] + a[j ^ (1 << i)];
	for(int i = 1; i < (1 << n); ++i){
		ans = max(ans, a[i].x + a[i].y);
		printf("%lld\n", ans);
	}
	return 0;
}

参考:https://zhuanlan.zhihu.com/p/651143987

标签:ch,前缀,int,SOSDP,while,高维,getchar
From: https://www.cnblogs.com/jiangchen4122/p/17741614.html

相关文章

  • 关于前缀和
    Part1前缀和定义前缀和可以简单理解为"数列的前n项的和"它是一种重要的预处理方式,能大大降低查询的时间复杂度一般来讲,我们会预处理一个数组。对数组中每个元素,我们记录从起始到该元素对应下标/状态所有数字的总和一维前缀和给定一个长度为\(n\)的数组\(a\),预......
  • 208. 实现 Trie (前缀树)
    Trie(发音类似"try")或者说前缀树是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。请你实现Trie类:Trie()初始化前缀树对象。voidinsert(Stringword)向前缀树中插入字符串word。booleansearch(St......
  • bitset 求解高维偏序
    菜,题简单,trick蠢,求别骂。记录今天做题的时候遇到的一个小trick。先看一道题:P3810【模板】三维偏序(陌上花开)。平凡的三维偏序板子,相信大家都会用CDQ/树套树/K-Dtree之类的优秀做法秒了吧!然后看这个题:求五维偏序,\(n\le3\times10^4\),保证每一维这\(n\)个数都是\(n\)......
  • 高维前缀和
    考虑高维前缀和,可以把每一维前缀和比如:三维前缀和for(i=1;i<=a;i++) for(j=1;j<=b;j++) for(k=1;k<=c;k++) f[i][j][k]+=f[i-1][j][k];for(i=1;i<=a;i++) for(j=1;j<=b;j++) for(k=1;k<=c;k++) f[i][j][k]+=f[i][j-1][k];for(i=1;i<=a;i++)......
  • 前缀树
    classTrieNode{public:intpass;intend;vector<TrieNode*>nexts;TrieNode(){pass=0;end=0;for(inti=0;i<26;i++)nexts.push_back(nullptr);}};classTrie{public:TrieNode......
  • 基本前缀和算法:一维前缀和、二维前缀和、子矩阵和
    1、一维前缀和以AcWing.795为例,题目要求如下:输入一个长度为N的整数序列。接下来再输入m个询问,每个询问输入一对l,r。对于每个询问,输出原序列中从第l个数到第r个数的和。输入格式第一行包含两个整数n和m。第二行包含n个整数,表示整数数列。接下来m行,每行包含两个整数l和r,表示一......
  • 力扣14.最长公共前缀
    编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。 示例1:输入:strs=["flower","flow","flight"]输出:"fl" 示例2:输入:strs=["dog","racecar","car"]输出:""解释:输入不存在公共前缀。 ......
  • windows批量删除指定前缀key
    直接上代码:del_keys_by_prefix.bat@echooffecho调用格式:[redis地址][redis密码][redis库号][待删除的key前缀带*]setkeysfile=redis-cached-keys.txtredis-cli-h%1-a%2-n%3keys%4>%keysfile%FOR/F%%iin(%keysfile%)DO(redis-cli-h%1-a%2-n%3de......
  • 前缀和与差分
    1.前缀和一维数组#include<iostream>usingnamespacestd;constintN=1e5+10;intmain(){intn,m,a[N],sum[N]={0};scanf("%d%d",&n,&m);for(inti=1;i<=n;i++){scanf("%d",&a[i]);sum[i]=s......
  • UVA-1401 - Remember the Word -----Trie前缀树
    题意:给出N个不同单词和一个长字符串S。把这个字符串分解成若干个单词的连接(单词尅重复使用),问有多少种方法?分析:令d[i]表示从字符i开始的字符串的分解方案数,则d[i]=sum{d[i+len[x]]|单词x是S[i...len]的前缀};详看《算法竞赛入门经典》---刘汝佳--Page208.......