poj 3370 Halloween treats(反演定理+鸽巢原理)

题意: 已知有n户人,每户会给小孩们一定数量的糖果(会给的数量假设小孩都已知),求小孩挑选哪几户人家,所得糖果总数能够使每个小孩得到相同数量的糖果,即是小孩数目的倍数?


思路:定理:

         设a1、a2……am是正整数的序列,则至少存在整数k和l,(1<=k<l<=m),使得和a(k+1) + a(k+2) + ... ... +al是m的倍数。

  证明:x%m的余数有(m-1)中可能,即设有(m-1)个鸽巢,设sn代表(a1+a2+...+an)则m个sn产生m个余数,根据鸽巢原理,一定至少有两个s的余数相等,将这连个s想减,中间a(k+1) + a(k+2) + ... ... +al一定是m的倍数。


代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#define N 100010
using namespace std;
struct Sum
{
    int r , h;
};
Sum R[N];

bool cmp(Sum a , Sum b)
{
    if(a.r==b.r) return a.h<b.h;
    return a.r<b.r;
}
int main()
{
    int c , n  , tmp;
    __int64 sum ;
    int flag ,b;
    while(scanf("%d%d",&c,&n)!=EOF && ( n+c ))
    {
        sum=0;  //cout<<"c= "<<c<<"  n= "<<n<<endl; 
        flag=-1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&tmp);
            sum+=tmp;
            //cout<<"sum = "<<sum<<endl;
            R[i].r=sum%c; // cout<<"R["<<i-1<<"].r= "<<R[i-1].r<<endl;
            R[i].h=i;
            if(R[i].r==0 ) flag=i; 
        }
     //   cout<<"flag=  "<<flag<<endl;
        if(flag==-1)
        {
            sort(R+1,R+1+n,cmp);
         //   for(int i=1;i<=n;i++) cout<<R[i].r<<" * ";cout<<endl;
         //   for(int i=1;i<=n;i++) cout<<R[i].h<<" & ";cout<<endl;
            for(int i=1;i<n;i++)  
            {
                if( R[i].r==R[i+1].r) {flag=R[i].h; b=R[i+1].h;} 
            }    
         //   cout<<"a=  "<<flag<<"  b= "<<b<<endl;
            if(flag==-1) printf("no sweets\n"); 
            else
            {
               for(int j=flag+1;j<b;j++)  printf("%d ",j);
               printf("%d\n",b); 
            }
        }
        else
        {
            for(int i=1;i<flag;i++) printf("%d ",i);
            printf("%d\n",flag);
        }
      
    }
    return 0;
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值