[海军国际项目办公室]石子游戏

Posted StaroForgin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[海军国际项目办公室]石子游戏相关的知识,希望对你有一定的参考价值。

石子游戏

题解

5 × 1 0 5 5\\times10^5 5×105的范围 O ( n log ⁡ 2   n ) O\\left(n\\log^2\\,n\\right) O(nlog2n)就离谱,还只开 1 s 1s 1s

看到这道题,我们应该很容易联想到 N i m Nim Nim游戏的方法,我们可以通过 s g sg sg函数来得到答案。
我们定义 s g i sg_{i} sgi表示对于数量为 i i i的石子堆的 s g sg sg函数值。
显然, s g i = m e x j = i − x i − 1 s g j sg_{i}=mex_{j=i-x}^{i-1}sg_{j} sgi=mexj=ixi1sgj,显然,答案当 x o r i = 1 n s g a i xor_{i=1}^{n}sg_{a_{i}} xori=1nsgai大于 0 0 0时是先手必胜的,否则是后手必胜的。
关于这个的证明可以自己去了解一下 N i m Nim Nim游戏。

而我们要求的是对于 x = 1 , 2 , . . . , n x=1,2,...,n x=1,2,...,n的所有情况的异或值。
我们考虑我们的 s g sg sg函数与 x x x有什么关系。很容易发现, s g i = ( i m o d     ( x + 1 ) ) sg_{i}=(i\\mod\\,(x+1)) sgi=(imod(x+1))
所以,我们的答案应该是 x o r i = 1 n ( a i m o d     ( x + 1 ) ) xor_{i=1}^{n}(a_{i}\\mod\\,(x+1)) xori=1n(aimod(x+1))
事实上只有出现奇数次的 a i a_{i} ai会有贡献,我们记 a i a_{i} ai出现次数的奇偶性为 c n t a i cnt_{a_{i}} cntai,那么答案应为 x o r i = 1 n ( c n t i i m o d     ( x + 1 ) ) xor_{i=1}^{n}(cnt_{i}i\\mod\\, (x+1)) xori=1n(cntiimod(x+1))
也就是说,我们每次只需要将出现奇数次的数模 x + 1 x+1 x+1的异或和求来就行了。
x x x又会从 1 1 1 n n n连续变化,考虑怎么求出这些答案。
它们都是模数在不断连续变化,我们很容易联想到Maximize GCD,通过调和级数来使我们的所有的枚举复杂度达到 log ⁡   n \\log\\,n logn

但这样也就要求快速求出一个区间里的异或和,但这个区间内并非每个数都有贡献。
由于这是异或的转移,很容易从二进制位上找到方向, [ 0 , 1 , . . . , 2 j − 1 − 1 ] [0,1,...,2^{j-1}-1] [0,1,...,2j11] [ 2 j − 1 , 2 j − 1 + 1 , . . . , 2 j ] [2^{j-1},2^{j-1}+1,...,2^{j}] [2j1,2j1+1,...,2j]的区别仅在于 2 j − 1 2^{j-1} 2j1位上是 0 0 0还是 1 1 1
所以我们可以通过倍增来快速求出答案。
我们定义 f i , j f_{i,j} fi,j表示从 i i i开始,也就是 i i i的贡献为 1 1 1,往后延伸 2 j 2^j 2j位,贡献不断增加,最后总的异或和的大小。
很明显, f f f的转移是与普通倍增的转移相似的,最多只需要判断后半部分的数的数量,如果是奇数就异或上 2 j − 1 2^{j-1} 2j1
同样,对于每个数的查询我们也是一段一段跳着去查询这一段的异或和,每次跳到模 ( x + 1 ) (x+1) (x+1) 1 1 1的位置,往后 x x x个的异或和。
同样地,这 x x x个也可以用上面的方法求出,我们从 2 log ⁡   x 2^{\\log\\,x} 2logx开始往下找,跳过去,后面跳的肯定包含我们前面跳的部分的二进制位,我们的步长是在逐渐缩小的,所以我们后面的会包含前面,同样通过奇偶性判断就行了。
每个 x x x会进行 ⌈ n x ⌉ \\lceil\\frac{n}{x}\\rceil xn次倍增的操作,根据调和级数,最后进行的倍增操作次数是 n ln ⁡   n n\\ln\\,n nlnn的。

时间复杂度 O ( n ln ⁡   n log ⁡   n ) O\\left(n\\ln\\,n\\log\\,n\\right) O(nlnnlogn)

源码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define MAXN 500005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;     
const LL INF=0x3f3f3f3f3f3f3f3f;  
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
char gc(){static char buf[5000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
#define getchar gc
char obuf[1<<22],*opt=obuf+(1<<22);
void pc(const int&ch){*--opt=ch;}
#define putchar pc
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s[海军国际项目办公室]矩阵

[海军国际项目办公室]打拳

[海军国际项目办公室]羽未

[海军国际项目办公室]假人

[海军国际项目办公室]快递

[海军国际项目办公室]生之花