[ARC222E] XOR Matching
Genius_Star · · 题解
或许更好的阅读体验。
思路:
设
这是显然的,因为
然后推式子(其中
于是本质上只需要对每个
即考虑
复杂度是
轻微卡常。
完整代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define lowbit(x) (x) & (-(x))
#define popcnt(x) __builtin_popcount(x)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N = 1.05e6 + 10, mod = 998244353;
inline ll read(){
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')
f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
inline int add(int x, int y){
return (x + y >= mod) ? (x + y - mod) : (x + y);
}
inline void getadd(int &x, int y){
x = (x + y >= mod) ? (x + y - mod) : (x + y);
}
inline int dec(int x, int y){
return (x < y) ? (x - y + mod) : (x - y);
}
inline void getdec(int &x, int y){
x = (x < y) ? (x - y + mod) : (x - y);
}
namespace FWT{
const int inv2 = (mod + 1) >> 1;
inline void FWT_xor(int *A, int n){
for(int i = 1; i < n; i <<= 1){
for(int j = 0; j < n; j += (i << 1)){
for(int k = 0; k < i; ++k){
int x = A[j + k], y = A[i + j + k];
A[j + k] = add(x, y);
A[i + j + k] = dec(x, y);
}
}
}
}
inline void IFWT_xor(int *A, int n){
for(int i = 1; i < n; i <<= 1){
for(int j = 0; j < n; j += (i << 1)){
for(int k = 0; k < i; ++k){
int x = A[j + k], y = A[i + j + k];
A[j + k] = 1ll * add(x, y) * inv2 % mod;
A[i + j + k] = 1ll * dec(x, y) * inv2 % mod;
}
}
}
}
};
struct Node{
int cnt, p;
inline bool operator<(const Node&rhs)const{
return cnt > rhs.cnt;
}
}A[N];
int n, m, lim, x, ans, B, lst;
int poww[N], ppow[N], h[N], hh[N], Ans[N];
inline void init(){
poww[0] = ppow[0] = 1;
for(int i = 1; i < N; ++i)
ppow[i] = poww[i] = 10ll * poww[i - 1] % mod;
}
int main(){
init();
n = read(), m = read();
lim = (1 << m);
B = sqrt(lim * m) + 1;
for(int i = 0; i < lim; ++i)
A[i].p = i;
while(n--){
x = read();
++A[x].cnt;
}
int cnt = 0;
for(int i = 0; i < lim; ++i)
if(A[i].cnt)
A[cnt++] = A[i];
stable_sort(A, A + cnt);
FWT::FWT_xor(ppow, lim);
for(int i = 0; i < cnt; ++i){
if(i % B == 0 && i){
for(int x = 0; x < lim; ++x)
hh[x] = h[x];
FWT::FWT_xor(hh, lim);
for(int x = 0; x < lim; ++x)
Ans[x] = 1ll * hh[x] * ppow[x] % mod;
FWT::IFWT_xor(Ans, lim);
lst = i;
}
getadd(ans, (A[i].cnt) >> 1);
int sum = Ans[A[i].p];
for(int j = lst; j < i; ++j)
getadd(sum, poww[A[i].p ^ A[j].p]);
// cerr << i << ' ' << sum << ' ' << lst << '\n';
getadd(ans, 1ll * A[i].cnt * sum % mod);
h[A[i].p] = 1;
}
write(ans);
return 0;
}