1 条题解
-
0
自动搬运
来自洛谷,原作者为

Great_Influence
**搬运于
2025-08-24 21:54:29,当前版本为作者最后更新于2018-01-03 20:11:44,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
迷之数论,证明比猜难。
首先,先猜一个结论:的分组方式可以从转移而来。
证明很简单。首先,分组要求可以转化为
$\forall i\in(0,n-1),\sum_{j\in S}j^n=\sum_{j\notin S}j^n$
其中S为其中一组。
先观察样例,可以发现,和都不在同一组内。于是,可以强行认为,这两个数一定不在同一组。那么上面的式子可以化为
设(t为奇数),在进行转化,可以发现:
原式左边

分析这个式子,发现除了最后一项1以外,其他几项就是i-1的要求,于是可以直接复制第i-1项的关系,在将第i-1项的关系在复制一遍并都加上,序列交换后接到后边,即可满足要求。
设箭头表示2k+1和2k+2中的选择方向,表示2k+2在集合S内,表示2k+1在集合内,那么可以发现集合应该是长这样:
$\downarrow\uparrow\uparrow\downarrow\uparrow\downarrow\downarrow\uparrow......$
分析可以发现,若为小于k最大的2的整次幂,则第个箭头和第个箭头是反向的。那么就对于每个询问暴力处理所在箭头的方向。注意处理出方向后,还要根据奇偶来判断是箭头还是箭尾。时间复杂度。
代码:
#include<bits/stdc++.h> #include<cctype> #define For(i,a,b) for(i=(a),i##end=(b);i<=i##end;++i) #define Forward(i,a,b) for(i=(a),i##end=(b);i>=i##end;--i) #define Rep(i,a,b) for(register int i=(a),i##end=(b);i<=i##end;++i) #define Repe(i,a,b) for(register int i=(a),i##end=(b);i>=i##end;--i) using namespace std; template<typename T>inline void read(T &x){ T s=0,f=1;char k=getchar(); while(!isdigit(k)&&k^'-')k=getchar(); if(!isdigit(k)){f=-1;k=getchar();} while(isdigit(k)){s=s*10+(k^48);k=getchar();} x=s*f; } void file(void){ #ifndef ONLINE_JUDGE freopen("water.in","r",stdin); freopen("water.out","w",stdout); #endif } static int n,q; void work() { read(n); read(q); static long long k,j; static bool is; Rep(i,1,q) { read(k);j=1;is=k&1;k=(k+1)>>1; while(j<=k)j<<=1; while(k>1) { while(j>=k)j>>=1; is^=1;k-=j; } printf("%c\n",is?'X':'Z'); } } int main(void){ file(); work(); return 0; } (题解比代码难打多了,题目想了10多min,题解打了将近30min。。。。。。)
- 1
信息
- ID
- 2902
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- (无)
- 递交数
- 0
- 已通过
- 0
- 上传者