Poj 3372 Candy Distribution

http://poj.org/problem?id=3372

一群小孩围成一个圈,老师顺时针发糖,分别每间隔0,1, 2, 3, 4……发一颗,问是否每个同学都有糖

数论得做法没想出来,打印了前几项看出来得规律,只要n是2^k则输出YES,否则输出NO

数论解法:

N个人围成一个圈,老师给N个人分糖果.第i次分到的人的编号是f(x) = (x*(x+1)/2)%N,这N个人能不能至少获得1个糖果.

易知必然存在i使得f(N - i - 1) = f(N + i) (mod N), 即周期为N,

只要判断f(x)能否构成N的完全剩余系,就能得出结果

f(x)为N的完全系,即证不存在i,j(i != j),使得f(i) == f(j)

                i*(i - 1)/2 = j*(j-1)/2 (mod N)

          (i-j)*(i+j+1)/2 = 0 (mod N)

其中(i-j)与(i+j+1)异号.

假设(i-j)为偶数

若(i-j)/2为偶数,当N为S*2^l(S奇数,l > 0),有解

若(i-j)/2为奇数,当N为P*Q,(P,Q是奇数),有解

类似当(i+j+1)为偶数时也一样.

因此N只能是2^l(l > 0)

另外学会得东西是如何判断n是否为2^k

n&(n-1) == 0     true

因为2得k次方得二进制中一定只有一个1

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
const int N = 100000;
bool Num[N];
int main(void)
{
    int n;

    while(cin>>n)
    {
//        memset(Num, 0 ,sizeof(Num));
//        Num[0] = 1;
//        int cnt = 0;
//        int count = 0, cur = 0;
//        while(cnt <= n)
//        {
//            cur += cnt;
//            cur %= n;
//            Num[cur] = 1;
//            cnt++;
//        }
//        int _flag = 1;
//        for(int i = 0;i < n;i++)
//            if(Num[i] == 0)
//                {_flag = 0;break;}
//        if(_flag)
//            cout<<"Yes"<<endl;
//        else
//            cout<<"No"<<endl;
        printf((n & n - 1) ? "NO\n" : "YES\n");
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值