传送门
- 关于 \(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;
}