题解 水晶

传送门

  • 关于 \(n\) 个数,每个有取值范围,求异或和为某一给定值的方案数:原题
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
#define INF 0x3f3f3f3f
#define N 200010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
	ll ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
ll lim[N], c;
int id[N], rk[N];
vector<int> to[N];
pair<int, int> e[N];
const ll mod=998244353;
// inline void md(ll& a, ll b) {a+=b; a=a>=mod?a-mod:a;}
inline void md(ll& a, ll b) {a=(a+b)%mod;}

// namespace force{
// 	int val[N], ans;
// 	void dfs(int u) {
// 		if (u>n) {
// 			int sum=0;
// 			for (int i=1; i<=n; ++i) sum^=val[i];
// 			if (sum!=c) return ;
// 			// for (int i=1; i<=m; ++i) if (val[e[i].fir]==val[e[i].sec]) return ;
// 			++ans;
// 			return ;
// 		}
// 		for (int i=0; i<=lim[u]; ++i) {
// 			val[u]=i;
// 			for (auto& v:to[u]) if (v<u && val[v]==val[u]) goto jump;
// 			dfs(u+1);
// 			jump: ;
// 		}
// 	}
// 	void solve() {
// 		dfs(1);
// 		cout<<ans<<endl;
// 	}
// }

// namespace task1{
// 	ll f[65][1<<10], ans;
// 	void solve() {
// 		int lim=1<<n;
// 		f[63][lim-1]=1;
// 		for (int i=62; ~i; --i) {
// 			for (int s=0,to; s<lim; ++s) if ((__builtin_popcount(s)&1?1:0)==(c&(1ll<<i)?1:0)) {
// 				for (int t=0; t<lim; ++t) if (f[i+1][t]) {
// 					for (int j=1; j<=n; ++j) if (t&(1<<j-1) && (((s&(1<<j-1))?1:0)>((::lim[j]&(1ll<<i))?1:0))) goto jump;
// 					to=t;
// 					for (int j=1; j<=n; ++j) if (t&(1<<j-1) && (((s&(1<<j-1))?1:0)<((::lim[j]&(1ll<<i))?1:0))) to^=1<<j-1;
// 					md(f[i][to], f[i+1][t]);
// 					// if (i==1) cout<<"add: "<<bitset<2>(s)<<' '<<bitset<2>(to)<<' '<<f[i+1][t]<<endl;
// 					jump: ;
// 				}
// 			}
// 		}
// 		for (int s=0; s<lim; ++s) md(ans, f[0][s]);
// 		printf("%lld\n", ans);
// 	}
// }

// namespace task2{
// 	int dsu[N], siz[N], top;
// 	ll minn[N], sta[N], f[65][1<<6];
// 	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
// 	inline void uni(int s, int t) {if ((s=find(s))!=(t=find(t))) siz[dsu[s]=t]+=siz[s];}
// 	ll calc() {
// 		int lim=1<<top; ll ans=0;
// 		memset(f, 0, sizeof(f));
// 		f[63][lim-1]=1;
// 		for (int i=62; ~i; --i) {
// 			for (int s=0,to; s<lim; ++s) if ((__builtin_popcount(s)&1?1:0)==(c&(1ll<<i)?1:0)) {
// 				for (int t=0; t<lim; ++t) if (f[i+1][t]) {
// 					for (int j=1; j<=top; ++j) if (t&(1<<j-1) && (((s&(1<<j-1))?1:0)>((sta[j]&(1ll<<i))?1:0))) goto jump;
// 					to=t;
// 					for (int j=1; j<=top; ++j) if (t&(1<<j-1) && (((s&(1<<j-1))?1:0)<((sta[j]&(1ll<<i))?1:0))) to^=1<<j-1;
// 					md(f[i][to], f[i+1][t]);
// 					jump: ;
// 				}
// 			}
// 		}
// 		for (int s=0; s<lim; ++s) md(ans, f[0][s]);
// 		return ans;
// 	}
// 	void solve() {
// 		int lim=1<<m; ll ans=0;
// 		for (int s=0; s<lim; ++s) {
// 			ll tem=1; top=0;
// 			for (int i=1; i<=n; ++i) dsu[i]=i, minn[i]=::lim[i], siz[i]=1;
// 			for (int i=1; i<=m; ++i) if (s&(1<<i-1)) uni(e[i].fir, e[i].sec);
// 			for (int i=1; i<=n; ++i) minn[find(i)]=min(minn[find(i)], ::lim[i]);
// 			for (int i=1; i<=n; ++i) if (find(i)==i) {
// 				if (siz[i]&1) sta[++top]=minn[i];
// 				else tem=tem*(minn[i]+1)%mod;
// 			}
// 			// cout<<"sta: "; for (int i=1; i<=top; ++i) cout<<sta[i]<<' '; cout<<endl;
// 			ans=(ans+(__builtin_popcount(s)&1?-1:1)*tem*calc())%mod;
// 			// cout<<"val: "<<tem*calc()<<endl;
// 		}
// 		printf("%lld\n", (ans%mod+mod)%mod);
// 	}
// }

// namespace task3{
// 	int dsu[N], siz[N], top;
// 	ll minn[N], sta[N], f[N][2][2];
// 	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
// 	inline void uni(int s, int t) {if ((s=find(s))!=(t=find(t))) siz[dsu[s]=t]+=siz[s];}
// 	ll calc() {
// 		// cout<<"calc: "<<endl;
// 		ll ans=0;
// 		for (int i=62; ~i; --i) {
// 			// cout<<"i: "<<i<<endl;
// 			int sum=0;
// 			for (int j=1; j<=top; ++j) f[j][0][0]=f[j][0][1]=f[j][1][0]=f[j][1][1]=0;
// 			f[0][0][0]=1;
// 			for (int j=1; j<=top; ++j) {
// 				ll tem=((sta[j]&((1ll<<i)-1))+1)%mod;
// 				// cout<<"tem: "<<tem<<endl;
// 				if (sta[j]&(1ll<<i)) {
// 					sum^=1;
// 					for (int k=0; k<2; ++k) 
// 						f[j][1][k]=(f[j][1][k]+f[j-1][1][k]*((1ll<<i)%mod)+f[j-1][0][k])%mod;
// 					for (int x=0; x<2; ++x)
// 						for (int y=0; y<2; ++y)
// 							f[j][x][y]=(f[j][x][y]+f[j-1][x][y^1]*tem)%mod;
// 				}
// 				else {
// 					for (int x=0; x<2; ++x)
// 						for (int y=0; y<2; ++y)
// 							f[j][x][y]=(f[j][x][y]+f[j-1][x][y]*tem)%mod;
// 				}
// 			}
// 			ans=(ans+f[top][1][(c&(1ll<<i))?1:0])%mod;
// 			if ((sum&1?1:0)!=((c&(1ll<<i))?1:0)) break;
// 			if (i==0) ans=(ans+1)%mod;
// 		}
// 		// cout<<"ans: "<<ans<<endl;
// 		return ans;
// 	}
// 	void solve() {
// 		int lim=1<<m; ll ans=0;
// 		for (int s=0; s<lim; ++s) {
// 			ll tem=1; top=0;
// 			for (int i=1; i<=n; ++i) dsu[i]=i, minn[i]=::lim[i], siz[i]=1;
// 			for (int i=1; i<=m; ++i) if (s&(1<<i-1)) uni(e[i].fir, e[i].sec);
// 			for (int i=1; i<=n; ++i) minn[find(i)]=min(minn[find(i)], ::lim[i]);
// 			for (int i=1; i<=n; ++i) if (find(i)==i) {
// 				if (siz[i]&1) sta[++top]=minn[i];
// 				else tem=tem*((minn[i]+1)%mod)%mod;
// 			}
// 			// cout<<"sta: "; for (int i=1; i<=top; ++i) cout<<sta[i]<<' '; cout<<endl;
// 			ans=(ans+(__builtin_popcount(s)&1?-1:1)*tem*calc())%mod;
// 			// cout<<"val: "<<tem*calc()<<endl;
// 		}
// 		printf("%lld\n", (ans%mod+mod)%mod);
// 	}
// }

namespace task{
	bool vis[1<<15], vis2[1<<15];
	int dsu[N], siz[N], lg[1<<15], top;
	ll minn[N], sta[N], f[N][2][2], g[1<<15], h[1<<15];
	struct pair_hash{inline size_t operator () (const pair<int, int>& t) const {return t.fir*13131+t.sec;}};
	cc_hash_table<pair<int, int>, ll, pair_hash> mp;
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	inline void uni(int s, int t) {if ((s=find(s))!=(t=find(t))) siz[dsu[s]=t]+=siz[s];}
	ll calc() {
		// cout<<"calc: "<<endl;
		ll ans=0;
		for (int i=62; ~i; --i) {
			// cout<<"i: "<<i<<endl;
			int sum=0;
			for (int j=1; j<=top; ++j) f[j][0][0]=f[j][0][1]=f[j][1][0]=f[j][1][1]=0;
			f[0][0][0]=1;
			for (int j=1; j<=top; ++j) {
				ll tem=((sta[j]&((1ll<<i)-1))+1)%mod;
				// cout<<"tem: "<<tem<<endl;
				if (sta[j]&(1ll<<i)) {
					sum^=1;
					for (int k=0; k<2; ++k) 
						f[j][1][k]=(f[j][1][k]+f[j-1][1][k]*((1ll<<i)%mod)+f[j-1][0][k])%mod;
					for (int x=0; x<2; ++x)
						for (int y=0; y<2; ++y)
							f[j][x][y]=(f[j][x][y]+f[j-1][x][y^1]*tem)%mod;
				}
				else {
					for (int x=0; x<2; ++x)
						for (int y=0; y<2; ++y)
							f[j][x][y]=(f[j][x][y]+f[j-1][x][y]*tem)%mod;
				}
			}
			ans=(ans+f[top][1][(c&(1ll<<i))?1:0])%mod;
			if ((sum&1?1:0)!=((c&(1ll<<i))?1:0)) break;
			if (i==0) ans=(ans+1)%mod;
		}
		// cout<<"ans: "<<ans<<endl;
		return ans;
	}
	void solve() {
		// int lim=1<<n;
		ll ans=0;
		// for (int i=0; i<n; ++i) lg[1<<i]=i+1;
		// for (int s=0; s<lim; ++s)
		// 	for (int i=1; i<=m; ++i)
		// 		if (s&(1<<e[i].fir-1) && s&(1<<e[i].sec-1)) {vis[s]=1; break;}
		// for (int s=0; s<lim; ++s) {
		// 	g[s]=!vis[s];
		// 	for (int t=s; t; t=(t-1)&s) if (t!=s && t&(s&-s))
		// 		g[s]=(g[s]-g[t]*(!vis[s^t]))%mod;
		// }
		// g[0]=0;
		// // cout<<"g: "; for (int s=0; s<lim; ++s) cout<<g[s]<<' '; cout<<endl;
		// mp[{0, 0}]=1;
		// for (int s=0; s<lim; ++s) {
		// 	for (int k=s; ~k; k=(k-1)&s) if (!k || mp.find({s, k})!=mp.end()) {
		// 		for (int t0=(~s)&(lim-1),t=t0; t; t=(t-1)&t0) if (t&(t0&-t0)) {
		// 			if (__builtin_popcount(t)&1) md(mp[{s|t, k|(t&-t)}], mp[{s, k}]*g[t]);
		// 			else md(mp[{s|t, k}], mp[{s, k}]*g[t]%mod*((::lim[lg[t0&-t0]]+1)%mod));
		// 		}
		// 		if (!k) break;
		// 	}
		// }
		// for (auto it:mp) if (it.fir.fir==lim-1) {
		// 	top=0;
		// 	for (int i=1; i<=n; ++i) if (it.fir.sec&(1<<i-1)) sta[++top]=::lim[i];
		// 	ans=(ans+it.sec*calc())%mod;
		// }
		for (int i=1; i<=n; ++i) sta[++top]=::lim[i];
		printf("%lld\n", (calc()%mod+mod)%mod);
	}
}

signed main()
{
	freopen("crystal.in", "r", stdin);
	freopen("crystal.out", "w", stdout);

	n=read(); c=0;
	for (int i=1; i<=n; ++i) lim[i]=read(), id[i]=i;
	// sort(id+1, id+n+1, [](int a, int b){return lim[a]<lim[b];});
	// for (int i=1; i<=n; ++i) rk[id[i]]=i;
	sort(lim+1, lim+n+1);
	// for (int i=1,u,v; i<=m; ++i) {
	// 	u=rk[read()]; v=rk[read()];
	// 	to[u].pb(v); to[v].pb(u);
	// 	e[i]={u, v};
	// }
	// if (!m) task1::solve();
	// else force::solve();
	// task2::solve();
	task::solve();

	return 0;
}
posted @ 2022-07-30 15:24  Administrator-09  阅读(2)  评论(0编辑  收藏  举报