【原创】POJ 3372 Candy Distribution

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,nn/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(i1)modn。(i从0开始的
首先解释为什么会出现循环.。
第一步,证明 f ( i ) = f ( i − 2 n ) ( i ≥ 2 n ) f(i)=f(i-2n) \quad (i\geq2n) f(i)=f(i2n)(i2n)。这个很显然可以跳过。(我想了好久)
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++(i1)modn=f(i2n)+f(2n)(modn)f(2n)=0f(2n)=2[0+1+2+3++(n1)]=n(n1)0(modn)nf(n)=0f(n)=n2(n1)0 2(n1)n

第二步,证明是对称的,比方说 对 于 n 为 偶 数 , 有 f ( i ) = f ( 2 n − i − 1 )    ( 0 ≤ i < n ) 对于n为偶数,有f(i)=f(2n-i-1) ~~(0\leq i\lt n) nf(i)=f(2ni1)  (0i<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(2ni1)f(i)i+12ni1=n(2n2i1)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(ni1)  (0i<2n1)i+1ni1=2n(n2i1)0(modn)
显 然 当 n 为 奇 数 时 , ( n − 2 i − 1 ) 为 偶 数 能 消 掉 分 母 2 , 然 后 这 个 式 子 就 是 n 的 倍 数 了 。 显然当n为奇数时,(n-2i-1)为偶数能消掉分母2,然后这个式子就是n的倍数了。 n(n2i1)2n

第三步,迅速发现根据类似于鸽笼原理的原理,奇数肯定不行,因为它循环节为 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),0i<n0j<i<n使f(i)=f(j)f(i)f(j)j+1i=2(i+j+1)(ij)0(modn)(i+j+1)(ij)1.iji+j+12ij0(modn)nn=(2p+1)(2q+1)i,j使f(i)=f(j){i+j+12p+12ij2q+1{ip+2q+1jp2q1i=jn2ijn=(2t+1)2ki,j便{i+j+12t+12ij2k{it+2kjt2kij2.ijni=jf(i)=f(j)n2kyesno
*/

上了个厕所回来,我发现以上写的太丑了于是重写了一份:
既 然 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} nn=(2t+1)2ki,j使f(i)=f(j)0j<i<nf(i)f(j)j+1i=2(i+j+1)(ij)0(modn)(i+j+1)(ij)(i+j+1)(ij)2ij{i+j+12t+12ij2k{it+2kjt2kijf(i)=f(j)noijfyesi,j便t=0n=2kyesno(ij)

第五步,写代码。

至于判断一个数是不是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号的两小时?
这代码能写两分钟吗?

还有不知道为什么我看着这个代码总觉得瘆人。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值