模拟赛-水晶

水晶

题意

给定长度为 \(n\) 的序列 \(\{m_n\}\) ,求满足条件的 \(\{a_n\}\) 的个数,条件是

  • \(\forall i\)\(0\le a_i\le m_i\)
  • \(\oplus_{i = 1} ^ n a_i = 0\)

答案对于 \(998244353\) 取模。

数据范围 \(0\le m_i<2 ^ {32}, 1\le n\le 2\times 10^{5}\)

题意

本来的想法是对于每一位可以做。结果并不是,是这样的,我们考虑,如果存在一个位置,他在 \(k\) 位上没有卡到上界,那么后面 \(k-1\) 位上肯定是可以异或和为 \(0\) 的。那么我们就枚举最大的一位 \(k\),满足 \(k\) 之前的位都卡上界。随后我们可以 \(dp\)。我们考虑枚举的位是 \(k\),令 \(U = 2 ^ k\),那么比如现在做到第 \(i\) 个,分两种情况进行讨论,令 \(dp[0/1]\) 表示异或和为 \(0/1\) 的方案数。

  • \(a_i\)\(k\) 位上是 \(1\),那么可以这一位上选 \(1\) 或者 \(0\),如果是 \(0\) 的话转移系数是 \(U\),否则他后面 \(k-1\) 位上的值(\(a_i \& (U - 1)\)
  • \(a_i\)\(k\) 位上是 \(0\),那么转移只能系数只能是后 \(k-1\) 位上的值

需要注意到是,我们需要满足前面 \(32 - k\) 上的位也异或和为 \(0\),这个判断一下就好。然后还有就是如果这一位上必须要有是 \(1\) 的位转移成 \(0\) 才行,这个可以对于这一位是1的个数是偶数的情况容斥一下,是奇数就不用考虑了,因为必然存在一个数字是1的选了 \(0\)

然后还有就是如果没有这个东西,也就是所有都卡着上界,然后还成立的话,也就是 \(m_i\) 异或起来是 \(0\) 的情况。

// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
	mt19937 eng;
	void init(int Seed) {return eng.seed(Seed);}
	int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
	x = 0;
	bool f = 0;
	char ch = gc();
	while (!isdigit(ch)) f = ch == '-', ch = gc();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
	if (f) x = -x;
}
inline void reads(char *s) {
	char ch = gc();
	while (isspace(ch)) ch = gc();
	while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
	*s = 0;
	return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
	read(x);
	read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
const int MOD = 998244353, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
	if (y < 0) {
		y %= MOD - 1;
		y += MOD - 1;
	}
	int ret = 1;
	for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
	return ret;
};
auto Mod = [] (int x) -> int {
	if (x >= MOD) return x - MOD;
	else if (x < 0) return x + MOD;
	else return x;
};
template<const int N_num, const int M_num>
struct Graph {
	int H[N_num];
	struct Edge {int to, lac;} e[M_num];
	inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
	inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
void add(int &x, int y) {if ((x += y) >= MOD) x -= MOD;}
const int MAXN = 2e5 + 10;
using ui = unsigned int;
int ans = 1, N;
ui A[MAXN];
int main() {
	freopen("crystal.in", "r", stdin);
    freopen("crystal.out", "w", stdout);
	// std::ios::sync_with_stdio(0);
	// cout << std::fixed << std::setprecision(8);
	// cin.tie(0);
	// cout.tie(0);
	qwq::init(20050112);
    read(N);
    for (int i = 1; i <= N; ++i) read(A[i]);
    for (int k = 31; k >= 0; --k) {
        array<int, 2U> dp{1, 0};
        int cnt = 0;
        int U = 1U << k;
        for (int i = 1, t; i <= N; ++i) {
            t = (A[i] & (U - 1)) + 1;
            if ((A[i] >> k) & 1) {
                ++cnt;
                decltype(dp) f = dp;
                dp[0] = ((ll) f[1] * t + (((ll) f[0]) << k)) % MOD;
                dp[1] = ((ll) f[0] * t + (((ll) f[1]) << k)) % MOD;
            } else dp[0] = (ll) dp[0] * t % MOD, dp[1] = (ll) dp[1] * t % MOD;
        }
        if (cnt & 1) {
            ans = Mod(ans - 1);
            ans = (ans + (ll) dp[0] * Ksm(inv2, k)) % MOD;
            break;
        } else {
            int tmp = 1;
            for (int i = 1; i <= N; ++i) tmp = (ll) tmp * ((A[i] & (U - 1)) + 1) % MOD;
            ans = (ans + (ll) Mod(dp[0] - tmp) * Ksm(inv2, k)) % MOD;
        }
    }
    printf("%d\n", ans);
	// cout << (-3 / 2);
	cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
	return (0-0);
}
// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
	mt19937 eng;
	void init(int Seed) {return eng.seed(Seed);}
	int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
	x = 0;
	bool f = 0;
	char ch = gc();
	while (!isdigit(ch)) f = ch == '-', ch = gc();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
	if (f) x = -x;
}
inline void reads(char *s) {
	char ch = gc();
	while (isspace(ch)) ch = gc();
	while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
	*s = 0;
	return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
	read(x);
	read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
const int MOD = 998244353, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
	if (y < 0) {
		y %= MOD - 1;
		y += MOD - 1;
	}
	int ret = 1;
	for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
	return ret;
};
auto Mod = [] (int x) -> int {
	if (x >= MOD) return x - MOD;
	else if (x < 0) return x + MOD;
	else return x;
};
template<const int N_num, const int M_num>
struct Graph {
	int H[N_num];
	struct Edge {int to, lac;} e[M_num];
	inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
	inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
void add(int &x, int y) {if ((x += y) >= MOD) x -= MOD;}
const int MAXN = 2e5 + 10;
using ui = unsigned int;
int ans = 1, N;
ui A[MAXN];
int main() {
	freopen("crystal.in", "r", stdin);
    freopen("crystal.out", "w", stdout);
	// std::ios::sync_with_stdio(0);
	// cout << std::fixed << std::setprecision(8);
	// cin.tie(0);
	// cout.tie(0);
	qwq::init(20050112);
    read(N);
    for (int i = 1; i <= N; ++i) read(A[i]);
    for (int k = 31; k >= 0; --k) {
        array<int, 2U> dp{1, 0};
        int cnt = 0;
        int U = 1U << k;
        for (int i = 1, t; i <= N; ++i) {
            t = (A[i] & (U - 1)) + 1;
            if ((A[i] >> k) & 1) {
                ++cnt;
                decltype(dp) f = dp;
                dp[0] = ((ll) f[1] * t + (((ll) f[0]) << k)) % MOD;
                dp[1] = ((ll) f[0] * t + (((ll) f[1]) << k)) % MOD;
            } else dp[0] = (ll) dp[0] * t % MOD, dp[1] = (ll) dp[1] * t % MOD;
        }
        if (cnt & 1) {
            ans = Mod(ans - 1);
            ans = (ans + (ll) dp[0] * Ksm(inv2, k)) % MOD;
            break;
        } else {
            int tmp = 1;
            for (int i = 1; i <= N; ++i) tmp = (ll) tmp * ((A[i] & (U - 1)) + 1) % MOD;
            ans = (ans + (ll) Mod(dp[0] - tmp) * Ksm(inv2, k)) % MOD;
        }
    }
    printf("%d\n", ans);
	// cout << (-3 / 2);
	cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
	return (0-0);
}
posted @ 2022-07-30 15:46  siriehn_nx  阅读(45)  评论(0编辑  收藏  举报