背景
[ 🤔 🤔 ⋯ 🤔 🤔 🤔 ⋯ 🤔 ⋮ ⋮ ⋱ ⋮ 🤔 🤔 ⋯ 🤔 ] \left[ \begin{matrix} 🤔&🤔&\cdots&🤔\\ 🤔&🤔&\cdots&🤔\\ \vdots&\vdots&\ddots&\vdots \\ 🤔&🤔&\cdots&🤔\\ \end{matrix} \right] ⎣⎢⎢⎢⎡🤔🤔⋮🤔🤔🤔⋮🤔⋯⋯⋱⋯🤔🤔⋮🤔⎦⎥⎥⎥⎤
题面
1 s, 64 mb .
题解
不难发现结论: f K , i = ⨁ j = 0 K − 1 ( K − 1 j ) a i + j f_{K,i}=\bigoplus_{j=0}^{K-1}{K-1\choose j}a_{i+j} fK,i=⨁j=0K−1(jK−1)ai+j 。
然后,肯定不能用卷积,我们要换个想法。
首先这个组合数是可以取模 2 的,因此动用Lucas定理, ( K − 1 j ) ≡ [ j a n d ( K − 1 ) = j ] {K-1\choose j}\equiv [j{\rm~and~}(K-1)=j] (jK−1)≡[j and (K−1)=j].
也就是说, f ( K , i ) f(K,i) f(K,i) 就等于所有 a i + j a_{i+j} ai+j 的异或和,满足 j j j 的二进制表示是 K − 1 K-1 K−1 的子集。
这是个高维前缀和的形式,我们可以通过类似倍增的预处理的方式解决。
令 d p [ i ] [ p ] dp[i][p] dp[i][p] 表示所有 a i + j a_{i+j} ai+j 的异或和,满足 j j j 的二进制表示是 K − 1 K-1 K−1 只保留最低 p p p 位的子集。
那就很好转移了,
d
p
[
i
]
[
0
]
=
a
i
dp[i][0]=a_{i}
dp[i][0]=ai ,若
K
−
1
K-1
K−1 第
p
p
p 位为 0,
d
p
[
i
]
[
p
]
=
d
p
[
i
]
[
p
−
1
]
dp[i][p]=dp[i][p-1]
dp[i][p]=dp[i][p−1],否则
d
p
[
i
]
[
p
]
=
d
p
[
i
]
[
p
−
1
]
⊕
d
p
[
i
+
2
p
−
1
]
[
p
−
1
]
dp[i][p]=dp[i][p-1]\oplus dp[i+2^{p-1}][p-1]
dp[i][p]=dp[i][p−1]⊕dp[i+2p−1][p−1]
第二维可以压缩掉,空间复杂度 O ( n ) O(n) O(n),时间复杂度 O ( n log n ) O(n\log n) O(nlogn) 。
CODE
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 3000005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define UIN unsigned int
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
//#define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
UIN dp[MAXN];
int main() {
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
n = read(); m = read()-1;
dp[1] = read();
for(int i = 2;i <= n;i ++) {
dp[i] = 1145141u*dp[i-1] + 1919u*i + 810u;
}
int nm = m;
while(nm) {
for(int i = 1;i+lowbit(nm) <= n;i ++) {
dp[i] ^= dp[i+lowbit(nm)];
}
nm -= lowbit(nm);
}
UIN ans = 0;
for(int i = 1;i <= n-m;i ++) {
UIN f = dp[i] ^ i;
ans += f*i;
}
AIput(ans,'\n');
return 0;
}