题目
题目要求的是求后缀和的异或和。首先我们考虑疑惑和情况下,什么时候为1,很显然,在当前二进制位0和1 的其中任意一个个数为奇数的时候才能让当前二进制位为1。
再观察到,题目中的模数很奇怪,他是。那么大于的数位都是不用考虑的。
变化的后缀和很好维护,但是难就难在求玩后缀和后的异或和上面。(赛时就没想明白,太弱了)
这个时候我们搬出树状数组用来统计每个数对相应的二进制位上的贡献。
ps:有一个点需要想一下,我如何去判断一个数只能对当前二进制位产生贡献。如果一个数相对当前二进制位产生贡献,那么我们就可以先将其对下一个更大的二进制位进行取模(限制上限)如果取完模之后发现大于当前二进制位,那么就很显然,能对当前位作出贡献。
举个例子:计算11这个数是否对第四个二进制位(8)作出贡献。首先11%16(8的下一个二进制位)=11;11>8,那么11就会对第四个二进制位作出贡献。那么此时就在树状数组记录第八位贡献下,从8开始++。
如此一来,就能决解统计问题了。随后就要解决查询问题。题目最后要求输出后缀和的异或和。
那么我们只需要逆推,依次计算对应二进制位上的1的数量就行
#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
// #include<priirity_queue>
#define lowbit(x) (x&(-x))
#define ll long long
#define int long long
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
// #define endl "\n"
#define pii pair<ll,ll>
#define psi pair<string, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define ls u << 1
#define rs u << 1 | 1
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
// static char buf[100000],*pa=buf,*pd=buf;
// #define gc pa==pd&&(pd=(pa=buf)+fread(buf,1,100000,stdin),pa==pd)?EOF:*pa++
// inline int read()
// {
// register int x(0);register char c(gc);
// while(c<'0'||c>'9')c=gc;
// while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
// return x;
// }
const int mod1 = 998244353;
const int mod2=1e9+7;
const int N = 3e6 + 60;
const ll INF = 1e15;
int n, m, k;
int z,len;
const int MOD=2097152;
int tr[25][MOD<<1];
int d[25];
int sum[N];
void add(int a[],int x,int k)
{x+=1;for(int i=x;i<=MOD;i+=lowbit(i)){a[i]+=k;}
}
int findd(int a[],int x)
{x+=1;int ans=0;for(int i=x;i;i-=lowbit(i))ans+=a[i];return ans;
}
void solve()
{len=0;d[0]=1;for(z=1;;z++){d[z]=d[z-1]*2;if(d[z]==MOD){z--;break;}}rep(i,0,z){add(tr[i],0,1);}//cout << 1 <<endl;int t;cin >> t;while(t--){int a,b;cin >> a >> b;while(a--){rep(i,0,z){add(tr[i],sum[len]%d[i+1],-1);}len--;}len++;sum[len]=sum[len-1]+b;rep(i,0,z){add(tr[i],sum[len]%d[i+1],1);} int ans=0;rep(i,0,z){int ant=sum[len]%d[i+1];int num=0;if(ant-d[i]>=0){num+=findd(tr[i],ant-d[i]);}num += findd(tr[i],ant +d[i])-findd(tr[i],ant);num%=2;ans += num*d[i];}cout << ans <<endl;}
}signed main()
{IOS;int _;_ = 1;//cin >> _;while(_ --) {// number++;solve();}return 0;
}