二维前缀和是总所周知的,它长这样:
\[f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i-1][j-1] \]这实际上是容斥原理。但我们还可以这样求 \(f\) 的前缀和:
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
f[i][j] += f[i][j - 1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
f[i][j] += f[i - 1][j];
两个循环交换位置也是可以的,很容易证明。这样,我们还可以推广到三维:
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
for(int k = 1; k <= n; k ++)
f[i][j][k] += f[i - 1][j][k];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
for(int k = 1; k <= n; k ++)
f[i][j][k] += f[i][j - 1][k];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
for(int k = 1; k <= n; k ++)
f[i][j][k] += f[i][j][k - 1];
这三个三重循环之间的顺序怎么交换都行,你可以先求j这个维度再求i这个维度最后再求k这个维度,都是等价的。\(n\) 维的同理。当每个维度都只有2个元素时,我们还可以直接状压dp。
由此我们可以引出这个题:
P5495 【模板】Dirichlet 前缀和
假设 \(x = ap_i^k\) ,\(y=ap_i^{k+1}\) ,其中 \(p_i\) 是 \(x\) 的某一个质因数,则很显然 \(b_y = b_x + 1\) 。那么,这不就是在 \(p_i\) 这个维度求前缀和吗?所以我们就可以直接高维前缀和了。code:
#include <bits/stdc++.h>
using namespace std;
#define debug
#define uint unsigned int
#define N 20000010
uint n;
uint a[N], p[N], cnt;
bool not_prime[N];
uint seed;
inline uint etnext() {
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
return seed;
}
void init() {
for (int i = 2; i <= n; i++) {
if (!not_prime[i]) {
p[++cnt] = i;
}
for (int j = 1; j <= cnt; j++) {
if (1ll * i * p[j] > 1ll * N) break;
not_prime[i * p[j]] = 1;
if (i % p[j] == 0) break;
}
}
}
signed main() {
// freopen("shuju.in", "r", stdin);
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> seed;
init();
for(int i = 1; i <= n; i ++){
a[i] = etnext();
}
for (int i = 1; i <= cnt; i++) {
for(int j = 1; j * p[i] <= n; j ++){
a[p[i] * j] += a[j];
}
}
uint ans = 0;
for(int i = 1; i <= n; i ++){
ans ^= a[i];
}
cout << ans;
return 0;
}
标签:前缀,int,seed,uint,维度,高维,define
From: https://www.cnblogs.com/yduck/p/18333221