POJ 3372 Candy Distribution
Description
N children standing in circle who are numbered 1 through N clockwise are waiting their candies. Their teacher distributes the candies by in the following way:
First the teacher gives child No.1 and No.2 a candy each. Then he walks clockwise along the circle, skipping one child (child No.3) and giving the next one (child No.4) a candy. And then he goes on his walk, skipping two children (child No.5 and No.6) and giving the next one (child No.7) a candy. And so on.
Now you have to tell the teacher whether all the children will get at least one candy?
Input
The input consists of several data sets, each containing a positive integer N (2 ≤ N ≤ 1,000,000,000).
Output
For each data set the output should be either “YES” or “NO”.
Sample Input
2
3
4
Sample Output
YES
NO
YES
翻译
有n个人围成圈圈,从0开始发糖,第i次发糖给a人以后,下一次给(a+i)%n人发,即顺时针数i个人。
给定n,问是否所有人都能吃到糖。
分析
首先发现是有循环节的(难道没有吗),n为奇数的时候循环节为n,n为偶数的时候循环节为2n,而且发现循环节都是对称的,也就是说,只需要跑{
n
/
2
+
1
,
n
为
奇
数
n
,
n
为
偶
数
{n/2+1,n为奇数}\atop{n,n为偶数}
n,n为偶数n/2+1,n为奇数次就可以了。
其实奇数就是第n次会回到0,所以循环节的长度是偶数的一半。
所以再次暴力,每个数只跑那么多次。这样可以比较快速的判断(小数据),发现只有2的幂才输出YES。
但是为什么呢?
记
f
(
i
)
f(i)
f(i)代表第i次给谁糖吃,显然
f
(
i
)
=
i
∗
(
i
−
1
)
2
m
o
d
n
f(i)=\frac{i*(i-1)}{2} \mod n
f(i)=2i∗(i−1)modn。(i从0开始的)
首先解释为什么会出现循环.。
第一步,证明
f
(
i
)
=
f
(
i
−
2
n
)
(
i
≥
2
n
)
f(i)=f(i-2n) \quad (i\geq2n)
f(i)=f(i−2n)(i≥2n)。这个很显然可以跳过。(我想了好久)
f
(
i
)
=
0
+
1
+
2
+
3
+
⋯
+
(
i
−
1
)
m
o
d
n
=
f
(
i
−
2
n
)
+
f
(
2
n
)
(
m
o
d
n
)
即
证
f
(
2
n
)
=
0
f
(
2
n
)
=
2
∗
[
0
+
1
+
2
+
3
+
⋯
+
(
n
−
1
)
]
=
n
∗
(
n
−
1
)
≡
0
(
m
o
d
n
)
然
后
奇
数
的
循
环
节
是
n
是
因
为
f
(
n
)
=
0
,
证
明
也
很
显
然
:
f
(
n
)
=
n
∗
(
n
−
1
)
2
≡
0
当
且
仅
当
(
n
−
1
)
2
为
整
数
即
n
为
奇
数
\begin{aligned} &f(i)=0+1+2+3+\cdots+(i-1) \mod n=f(i-2n)+f(2n) \pmod{n}\\ &即证f(2n)=0\\ &f(2n)=2*[0+1+2+3+\cdots+(n-1)]=n*(n-1)\equiv 0\pmod{n}\\ &\\ &然后奇数的循环节是n是因为f(n)=0,证明也很显然:\\ &f(n)=n*\frac{(n-1)}{2}\equiv 0 ~当且仅当\frac{(n-1)}{2}为整数即n为奇数\\ &\\ &\\ \end{aligned}
f(i)=0+1+2+3+⋯+(i−1)modn=f(i−2n)+f(2n)(modn)即证f(2n)=0f(2n)=2∗[0+1+2+3+⋯+(n−1)]=n∗(n−1)≡0(modn)然后奇数的循环节是n是因为f(n)=0,证明也很显然:f(n)=n∗2(n−1)≡0 当且仅当2(n−1)为整数即n为奇数
第二步,证明是对称的,比方说
对
于
n
为
偶
数
,
有
f
(
i
)
=
f
(
2
n
−
i
−
1
)
(
0
≤
i
<
n
)
对于n为偶数,有f(i)=f(2n-i-1) ~~(0\leq i\lt n)
对于n为偶数,有f(i)=f(2n−i−1) (0≤i<n)(注意以下的i是从0开始的)
等
价
于
证
f
(
2
n
−
i
−
1
)
−
f
(
i
)
≡
∑
i
+
1
2
n
−
i
−
1
=
n
(
2
n
−
2
i
−
1
)
≡
0
(
m
o
d
n
)
。
等价于证f(2n-i-1)-f(i)\equiv\sum_{i+1}^{2n-i-1}= n(2n-2i-1)\equiv 0 \pmod{n}。
等价于证f(2n−i−1)−f(i)≡∑i+12n−i−1=n(2n−2i−1)≡0(modn)。
这就很显然了。
对于奇数呢?
f
(
i
)
=
f
(
n
−
i
−
1
)
(
0
≤
i
<
n
−
1
2
)
⟺
∑
i
+
1
n
−
i
−
1
=
n
(
n
−
2
i
−
1
)
2
≡
0
(
m
o
d
n
)
f(i)=f(n-i-1) ~~(0\leq i\lt \frac{n-1}{2})\iff\sum_{i+1}^{n-i-1}=\frac{n(n-2i-1)}{2}\equiv0\pmod{n}
f(i)=f(n−i−1) (0≤i<2n−1)⟺∑i+1n−i−1=2n(n−2i−1)≡0(modn)
显
然
当
n
为
奇
数
时
,
(
n
−
2
i
−
1
)
为
偶
数
能
消
掉
分
母
2
,
然
后
这
个
式
子
就
是
n
的
倍
数
了
。
显然当n为奇数时,(n-2i-1)为偶数能消掉分母2,然后这个式子就是n的倍数了。
显然当n为奇数时,(n−2i−1)为偶数能消掉分母2,然后这个式子就是n的倍数了。
第三步,迅速发现根据类似于鸽笼原理的原理,奇数肯定不行,因为它循环节为 n n n,而且 n n n个还是对称的,也就是说,循环节里最多只会有 n / 2 + 1 {n/2+1} n/2+1个不同的数,不可能填满 n n n个人。
第四步,那么对于偶数呢?因为循环节是 2 n 2n 2n,而前 n n n个和后 n n n个是对称的,因此我们只能期待这前 n n n个能把 n n n个人走完。这就要求前 n n n个人里没有重复的。换句话来说, f ( i ) f(i) f(i)要构成 n n n的完全剩余系。
警告:以下注释中的求法极丑,建议跳过注释里的内容。
/*
现
在
我
们
要
找
出
对
于
怎
样
的
偶
数
n
,
使
得
f
(
i
)
,
0
≤
i
<
n
中
存
在
或
是
不
存
在
相
等
的
两
项
。
设
存
在
0
≤
j
<
i
<
n
使
得
f
(
i
)
=
f
(
j
)
,
则
有
f
(
i
)
−
f
(
j
)
≡
∑
j
+
1
i
=
(
i
+
j
+
1
)
(
i
−
j
)
2
≡
0
(
m
o
d
n
)
易
发
现
(
i
+
j
+
1
)
与
(
i
−
j
)
异
奇
偶
性
,
于
是
分
类
讨
论
:
1.
如
果
i
−
j
是
偶
数
,
则
i
+
j
+
1
是
奇
数
:
①
如
果
i
−
j
2
是
奇
数
,
也
就
是
说
奇
数
∗
奇
数
≡
0
(
m
o
d
n
)
。
那
么
当
n
是
n
=
(
2
p
+
1
)
∗
(
2
q
+
1
)
的
形
式
时
,
我
们
一
定
可
以
找
到
一
对
不
相
等
的
i
,
j
使
得
f
(
i
)
=
f
(
j
)
。
为
什
么
呢
?
我
们
随
意
列
一
个
一
元
二
次
方
程
组
{
i
+
j
+
1
≡
2
p
+
1
i
−
j
2
≡
2
q
+
1
然
后
解
得
{
i
≡
p
+
2
q
+
1
j
≡
p
−
2
q
−
1
,
只
要
i
≠
j
,
就
可
行
,
而
这
显
然
是
可
行
的
。
再
说
了
,
我
们
在
第
三
步
不
是
已
经
论
证
完
了
n
为
奇
数
的
时
候
吗
?
②
如
果
i
−
j
2
是
偶
数
,
发
现
对
于
n
=
(
2
t
+
1
)
∗
2
k
这
种
形
式
,
也
可
以
找
到
i
,
j
。
(
这
次
要
分
奇
偶
来
列
式
因
此
不
能
随
便
地
)
列
一
个
一
元
二
次
方
程
组
{
i
+
j
+
1
≡
2
t
+
1
i
−
j
2
≡
2
k
解
得
{
i
≡
t
+
2
k
j
≡
t
−
2
k
,
这
个
i
和
j
也
显
然
不
相
等
。
故
成
立
。
2.
如
果
i
−
j
是
奇
数
,
可
以
进
行
类
似
的
讨
论
得
出
相
同
的
结
果
。
综
上
所
述
,
只
要
n
有
奇
因
子
,
就
一
定
可
以
找
出
i
≠
j
,
f
(
i
)
=
f
(
j
)
。
所
以
当
且
仅
当
n
为
2
k
时
,
输
出
y
e
s
,
否
则
输
出
n
o
。
\begin{aligned} &现在我们要找出对于怎样的偶数n,使得f(i) ,0\leq i\lt n中存在或是不存在相等的两项。\\ &设存在0\leq j\lt i\lt n使得f(i)=f(j),则有f(i)-f(j)\equiv\sum_{j+1}^{i} =\frac{(i+j+1)(i-j)}{2}\equiv0\pmod{n}\\ &易发现(i+j+1)与(i-j)异奇偶性,于是分类讨论:\\ &1.如果i-j是偶数,则i+j+1是奇数:\\ &①如果\frac{i-j}{2}是奇数,也就是说奇数*奇数\equiv 0\pmod n 。\\ &那么当n是n=(2p+1)*(2q+1)的形式时,我们一定可以找到一对不相等的i,j使得f(i)=f(j) 。\\ &为什么呢?我们随意列一个一元二次方程组\begin{cases} i+j+1\equiv 2p+1 \\ \frac{i-j}{2} \equiv 2q+1 \end{cases}\\ &然后解得\begin{cases} i\equiv p+2q+1\\ j \equiv p-2q-1 \end{cases},只要i\neq j,就可行,而这显然是可行的。\\ &再说了,我们在第三步不是已经论证完了n为奇数的时候吗? \\ &②如果\frac{i-j}{2}是偶数,发现对于n=(2t+1)*2^k这种形式,也可以找到i,j。\\ &(这次要分奇偶来列式因此不能随便地)列一个一元二次方程组\begin{cases} i+j+1\equiv 2t+1 \\ \frac{i-j}{2} \equiv 2^k \end{cases}\\ &解得\begin{cases} i\equiv t+2^k\\ j \equiv t-2^k \end{cases},这个i和j也显然不相等。故成立。\\ &2.如果i-j是奇数,可以进行类似的讨论得出相同的结果。\\ &综上所述,只要n有奇因子,就一定可以找出i\neq j,f(i)=f(j)。\\ &所以当且仅当n为2^k时,输出yes,否则输出no。\\ \end{aligned}
现在我们要找出对于怎样的偶数n,使得f(i),0≤i<n中存在或是不存在相等的两项。设存在0≤j<i<n使得f(i)=f(j),则有f(i)−f(j)≡j+1∑i=2(i+j+1)(i−j)≡0(modn)易发现(i+j+1)与(i−j)异奇偶性,于是分类讨论:1.如果i−j是偶数,则i+j+1是奇数:①如果2i−j是奇数,也就是说奇数∗奇数≡0(modn)。那么当n是n=(2p+1)∗(2q+1)的形式时,我们一定可以找到一对不相等的i,j使得f(i)=f(j)。为什么呢?我们随意列一个一元二次方程组{i+j+1≡2p+12i−j≡2q+1然后解得{i≡p+2q+1j≡p−2q−1,只要i=j,就可行,而这显然是可行的。再说了,我们在第三步不是已经论证完了n为奇数的时候吗?②如果2i−j是偶数,发现对于n=(2t+1)∗2k这种形式,也可以找到i,j。(这次要分奇偶来列式因此不能随便地)列一个一元二次方程组{i+j+1≡2t+12i−j≡2k解得{i≡t+2kj≡t−2k,这个i和j也显然不相等。故成立。2.如果i−j是奇数,可以进行类似的讨论得出相同的结果。综上所述,只要n有奇因子,就一定可以找出i=j,f(i)=f(j)。所以当且仅当n为2k时,输出yes,否则输出no。
*/
上了个厕所回来,我发现以上写的太丑了于是重写了一份:
既
然
n
是
偶
数
了
,
设
n
=
(
2
t
+
1
)
∗
2
k
。
那
么
现
在
我
们
要
试
图
找
出
一
对
不
相
等
的
数
i
,
j
,
使
得
f
(
i
)
=
f
(
j
)
。
设
0
≤
j
<
i
<
n
,
则
有
f
(
i
)
−
f
(
j
)
≡
∑
j
+
1
i
=
(
i
+
j
+
1
)
(
i
−
j
)
2
≡
0
(
m
o
d
n
)
易
发
现
(
i
+
j
+
1
)
与
(
i
−
j
)
异
奇
偶
性
,
所
以
我
们
分
类
讨
论
:
如
果
(
i
+
j
+
1
)
是
奇
数
,
则
(
i
−
j
)
是
偶
数
,
而
且
i
−
j
2
还
得
是
偶
数
;
于
是
这
种
情
况
下
我
们
就
可
以
列
出
方
程
:
{
i
+
j
+
1
≡
2
t
+
1
i
−
j
2
≡
2
k
解
得
{
i
≡
t
+
2
k
j
≡
t
−
2
k
,
如
果
这
个
i
和
j
不
相
等
的
话
,
说
明
可
以
找
到
f
(
i
)
=
f
(
j
)
的
,
就
要
输
出
n
o
;
如
果
i
和
j
相
等
的
话
,
就
说
明
找
不
到
相
同
的
f
值
,
也
就
可
以
输
出
y
e
s
。
那
么
到
底
什
么
时
候
i
,
j
相
等
呢
?
随
便
搞
搞
就
知
道
当
且
仅
当
t
=
0
时
,
即
n
=
2
k
时
,
输
出
y
e
s
,
否
则
输
出
n
o
。
如
果
(
i
−
j
)
是
奇
数
,
可
以
用
类
似
的
步
骤
得
出
同
一
个
结
论
。
(
应
该
吧
)
\begin{aligned} &既然n是偶数了,设n=(2t+1)*2^k。\\ &那么现在我们要试图找出一对不相等的数i,j,使得f(i)=f(j)。\\ &设0\leq j\lt i\lt n,则有f(i)-f(j)\equiv\sum_{j+1}^{i} =\frac{(i+j+1)(i-j)}{2}\equiv0\pmod{n}\\ &易发现(i+j+1)与(i-j)异奇偶性,所以我们分类讨论:\\ &如果(i+j+1)是奇数,则(i-j)是偶数,而且\frac{i-j}{2}还得是偶数;\\ &于是这种情况下我们就可以列出方程:\begin{cases} i+j+1\equiv 2t+1 \\ \frac{i-j}{2} \equiv 2^k \end{cases}\\ &解得\begin{cases} i\equiv t+2^k\\ j \equiv t-2^k \end{cases},如果这个i和j不相等的话,说明可以找到f(i)=f(j)的,就要输出no;如果i和j相等的话,就说明找不到相同的f值,也就可以输出yes。\\ &那么到底什么时候i,j相等呢?随便搞搞就知道当且仅当t=0时,即n=2^k时,输出yes,否则输出no。\\ &如果(i-j)是奇数,可以用类似的步骤得出同一个结论。(应该吧)\\ \end{aligned}
既然n是偶数了,设n=(2t+1)∗2k。那么现在我们要试图找出一对不相等的数i,j,使得f(i)=f(j)。设0≤j<i<n,则有f(i)−f(j)≡j+1∑i=2(i+j+1)(i−j)≡0(modn)易发现(i+j+1)与(i−j)异奇偶性,所以我们分类讨论:如果(i+j+1)是奇数,则(i−j)是偶数,而且2i−j还得是偶数;于是这种情况下我们就可以列出方程:{i+j+1≡2t+12i−j≡2k解得{i≡t+2kj≡t−2k,如果这个i和j不相等的话,说明可以找到f(i)=f(j)的,就要输出no;如果i和j相等的话,就说明找不到相同的f值,也就可以输出yes。那么到底什么时候i,j相等呢?随便搞搞就知道当且仅当t=0时,即n=2k时,输出yes,否则输出no。如果(i−j)是奇数,可以用类似的步骤得出同一个结论。(应该吧)
第五步,写代码。
至于判断一个数是不是2的幂的方法,略。
代码
#include<cstdio>
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
while(n%2==0) n/=2;
puts(n==1?"YES":"NO");
}
}
说在后面
写题解写了我两天?
8月22号的两小时+8月30号的两小时?
这代码能写两分钟吗?
还有不知道为什么我看着这个代码总觉得瘆人。