[校内模拟] 200617Practice CQOI 2018

T1 Android

状压DP
不会,咕

T2 Baguenaudier

我有一个九连环,但是从来没玩过,初中的时候无聊看玩法说明,看到一句话:考虑先拆掉最远(最靠左)的环
这句话救了今天的我

n n n连环需要 a n a_n an次打开
考虑后 n − 2 n-2 n2个环, a n − 2 a_{n-2} an2次打开,此时环可以表示为 11000 ⋯ 0 11000\cdots0 110000
拆掉第一个得到 01000 ⋯ 0 01000\cdots0 010000
倒着把后 n − 2 n-2 n2个环加回来 0111 ⋯ 1 0111\cdots1 01111
现在就只需要 a n − 1 a_{n-1} an1次就可以打开后 n − 1 n-1 n1个环了

于是得到递推式 a n = a n − 1 + 2 a n − 2 + 1 a_n=a_{n-1}+2a_{n-2}+1 an=an1+2an2+1
并且发现了奇偶规律:
a n = { 2 a n − 1 , n m o d    2 = 0 , 2 a n − 1 + 1 , n m o d    2 = 1. a_n=\left\{ \begin{aligned} &2a_{n-1}, && n\mod2=0,\\ &2a_{n-1}+1, && n\mod2=1. \end{aligned} \right. an={2an1,2an1+1,nmod2=0,nmod2=1.

机房大佬提供了好多种做法,我们继续推柿子

  1. 蒲巨
    蒲巨前面的推导有点日龙,太复杂了点(他设了好几个变量,对于他还好,但是对于我这种一见一堆变量名就头晕的菜鸡来说简直是天书)
    不过有一个好处就是可以迅速发现规律:
    a n a_n an转化为二进制,发现 n m o d    2 = 1 n\mod2=1 nmod2=1时, a n = ( 10101 ⋯ 101 ) 2 a_n=(10101\cdots 101)_2 an=(10101101)2 n m o d    2 = 0 n\mod2=0 nmod2=0 a n = ( 10101 ⋯ 10 ) 2 a_n=(10101\cdots 10)_2 an=(1010110)2,且这些数的位数都是 n n n
    二进制+高精=AC

  2. stc wss
    他说这是他网课时被苏老唯一一次抽起来回答问题的题。。。
    奇数项抽出来 a n = 4 a n − 2 + 1 ,   n ∈ O d d a_n=4a_{n-2}+1,\ n\in \mathrm{Odd} an=4an2+1, nOdd,记为 { b n } \{b_n\} {bn},则 b n = 4 n − 1 3 b_n=\frac{4^n-1}{3} bn=34n1
    高精+快速幂=AC

  3. sto sj
    苏老,对不起,这是你上课讲过的,我数学没学好,sj哥哥太巨了
    a n = a n + 1 + 2 a n + 2 + 1 ⇒ a n + a n + 1 = 2 ( a n + 1 + a n + 2 ) + 1 ⇒ a n + a n − 1 = 2 n − 1 \begin{aligned} &a_n=a_{n+1}+2a_{n+2}+1\\ \Rightarrow&a_n+a_{n+1}=2(a_{n+1}+a_{n+2})+1\\ \Rightarrow&a_n+a_{n-1}=2^n-1 \end{aligned} an=an+1+2an+2+1an+an+1=2(an+1+an+2)+1an+an1=2n1
    大概这样
    高精+快速幂=AC

几种方法最后得到的都是 a i = ⌊ 2 i + 1 3 ⌋ a_i=\lfloor\frac{2^{i+1}}{3}\rfloor ai=32i+1

考场上高精写炸了,就只有暴力分(不会高精度但会FFT的菜鸡感到很淦)
所以就咕了

T3 Xor

莫队,前缀和

考虑 a a a的前缀和 p p p,有
⨁ i = l r a i = p l − 1 ⊕ p r = k \bigoplus_{i=l}^ra_i=p_{l-1}\oplus p_r=k i=lrai=pl1pr=k

考虑
p l − 1 ⊕ p r = k ⇒ p l − 1 = k ⊕ p r p_{l-1}\oplus p_r=k \Rightarrow p_{l-1}=k\oplus p_r pl1pr=kpl1=kpr
莫队可以统计
开个数组记录区间内不同前缀和的个数

关于莫队的区间修改,考虑加入一个点,那么要加入这个点与区间内所有点的关系,再统计这个点,(因为这个点还不在区间里面);删去点反之

莫队是对左节点(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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值