文章目录
T1 Android
状压DP
不会,咕
T2 Baguenaudier
我有一个九连环,但是从来没玩过,初中的时候无聊看玩法说明,看到一句话:考虑先拆掉最远(最靠左)的环
这句话救了今天的我
记连环需要次打开
考虑后个环,次打开,此时环可以表示为
拆掉第一个得到
倒着把后个环加回来
现在就只需要次就可以打开后个环了
于是得到递推式
并且发现了奇偶规律:
机房大佬提供了好多种做法,我们继续推柿子
-
蒲巨
蒲巨前面的推导有点日龙,太复杂了点(他设了好几个变量,对于他还好,但是对于我这种一见一堆变量名就头晕的菜鸡来说简直是天书)
不过有一个好处就是可以迅速发现规律:
将转化为二进制,发现时,;时,且这些数的位数都是
二进制+高精=AC -
stc wss
他说这是他网课时被苏老唯一一次抽起来回答问题的题。。。
奇数项抽出来,记为,则
高精+快速幂=AC -
sto sj
苏老,对不起,这是你上课讲过的,我数学没学好,sj哥哥太巨了
大概这样
高精+快速幂=AC
几种方法最后得到的都是
考场上高精写炸了,就只有暴力分(不会高精度但会FFT的菜鸡感到很淦)
所以就咕了
T3 Xor
莫队,前缀和
考虑的前缀和,有
考虑
莫队可以统计
开个数组记录区间内不同前缀和的个数
关于莫队的区间修改,考虑加入一个点,那么要加入这个点与区间内所有点的关系,再统计这个点,(因为这个点还不在区间里面);删去点反之
莫队是对左节点(left)分块!!
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define re register
inline int in{
int i=0,f=1;char ch=0;
while(ch!='-'&&!isdigit(ch)) ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int NNN=5e5+5;
int n,m,k,siz;
int p[NNN];//prefix
int cnt[NNN];//count of each exclusive or sum in each section
int num[NNN];//record ans of each query
struct Query{
int l,r,id,pos;
}q[NNN];
inline bool cmp1(const Query u,const Query v){
if(u.pos!=v.pos) return u.pos<v.pos;
return u.r<v.r;
}
int main(){
n=in,m=in,k=in,siz=sqrt(n);
for(re int i=1;i<=n;++i) p[i]=p[i-1]^in;
for(re int i=1;i<=m;++i){
q[i].l=in-1;
q[i].r=in;
q[i].id=i;
q[i].pos=(q[i].l-1)/siz+1;
}
sort(q+1,q+m+1,cmp1);
re int l=1,r=0,ans=0;
for(re int i=1;i<=m;++i){
while(l<q[i].l){
--cnt[p[l]];
ans-=cnt[p[l]^k];
++l;
}
while(l>q[i].l){
--l;
ans+=cnt[p[l]^k];
++cnt[p[l]];
}
while(r<q[i].r){
++r;
ans+=cnt[p[r]^k];
++cnt[p[r]];
}
while(r>q[i].r){
--cnt[p[r]];
ans-=cnt[p[r]^k];
--r;
}
num[q[i].id]=ans;
}
for(re int i=1;i<=m;++i)
printf("%d\n",num[i]);
return 0;
}