poj 3370 Halloween treats (剩余类,抽屉原理)

Halloween treats
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7470   Accepted: 2742   Special Judge

Description

Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a child will get nothing if it is too late. To avoid conflicts, the children have decided they will put all sweets together and then divide them evenly among themselves. From last year's experience of Halloween they know how many sweets they get from each neighbour. Since they care more about justice than about the number of sweets they get, they want to select a subset of the neighbours to visit, so that in sharing every child receives the same number of sweets. They will not be satisfied if they have any sweets left which cannot be divided.

Your job is to help the children and present a solution.

Input

The input contains several test cases.
The first line of each test case contains two integers c and n (1 ≤ c ≤ n ≤ 100000), the number of children and the number of neighbours, respectively. The next line contains n space separated integers a1 , ... , an (1 ≤ ai ≤ 100000 ), where ai represents the number of sweets the children get if they visit neighbour i.

The last test case is followed by two zeros.

Output

For each test case output one line with the indices of the neighbours the children should select (here, index i corresponds to neighbour i who gives a total number of ai sweets). If there is no solution where each child gets at least one sweet print "no sweets" instead. Note that if there are several solutions where each child gets at least one sweet, you may print any of them.

Sample Input

4 5
1 2 3 7 5
3 6
7 11 2 5 13 17
0 0

Sample Output

3 5
2 3 4

Source

 
昨天那道签到的数学题没搞出来不开心.
是时候刷一波数学了
 
这题题意是说,从n个数中任选m个,使得m个的和为c的倍数.
如果有解,输出选的数的下标,否则输出无解字符串.
 
抽屉原理的原始描述是,如果有n+1个物品,有n个抽屉,那么至少有一个抽屉有2个物品.
抽屉原理我们可以退出一个结论,对于任意 n个自然数,一定有连续的一段和为n的倍数.
证明如下:
  设这n个自然数分别为a1,a2,a3,a4....an
  处理一个前缀和sum[i] = (sum[i-1] + a[i])%n
  因为n的剩余类有n种,分别为0,1,2...n-1
  所以sum[1],sum[2],sum[3]..sum[n]
  那么sum[1],sum[2],sum[3]...sum[n]最多也有n种.
  我们分情况讨论:
    (1)sum[1],sum[2],sum[3]...sum[n]互不相同,那么一定存在sum[i]=0,也就是前i个数的和为n的倍数.
    (2)情况(1)的反面,也就是存在sum[i]==sum[j]  (i<j),那么 从a[i+1] 到 a[j]的和就是n的倍数. 
 
 
因为题目中的数据 c<=n ,所以解一定存在.
具体做法就是处理出来一个前缀和%c
然后如果有0,则为解,输出.
否则记录sum[i]%d出现的位置,存在一个数组里
如果sum[i]%d第二次出现,就输出这段下标.
 
嘛,大括号换风格了....
都写开代码太长了==
 1 /*************************************************************************
 2     > File Name: code/poj/3370.cpp
 3     > Author: 111qqz
 4     > Email: rkz2013@126.com 
 5     > Created Time: 2015年08月21日 星期五 13时06分34秒
 6  ************************************************************************/
 7 
 8 #include<iostream>
 9 #include<iomanip>
10 #include<cstdio>
11 #include<algorithm>
12 #include<cmath>
13 #include<cstring>
14 #include<string>
15 #include<map>
16 #include<set>
17 #include<queue>
18 #include<vector>
19 #include<stack>
20 #define y0 abc111qqz
21 #define y1 hust111qqz
22 #define yn hez111qqz
23 #define j1 cute111qqz
24 #define tm crazy111qqz
25 #define lr dying111qqz
26 using namespace std;
27 #define REP(i, n) for (int i=0;i<int(n);++i)  
28 typedef long long LL;
29 typedef unsigned long long ULL;
30 const int inf = 0x3f3f3f3f;
31 const int N=1E5+7;
32 int a[N];
33 LL sum[N];
34 int p[N];
35 int n,c;
36 int main()
37 {
38     while (~scanf("%d %d",&c,&n)){
39     if (c==0&&n==0) break;
40     sum[0]  = 0;
41     for ( int i  = 1 ; i <= n ;i++){
42         scanf("%d",&a[i]);
43         a[i] = a[i] % c;
44         sum[i] = (sum[i-1] + a[i])%c;
45     }
46     memset(p,0,sizeof(p));
47     for ( int i = 1 ; i <= n ; i++ ){
48         if (sum[i]==0){
49         for ( int  j = 1 ;  j <= i ; j++){
50             cout<<j<<" ";
51            // cout<<"wang wang wang !"<<endl;
52         }
53         cout<<endl;
54         break;
55         }
56         if (p[sum[i]]){
57         for ( int  j = p[sum[i]]+1 ; j <= i ; j++){
58             cout<<j<<" ";
59     //        cout<<"111qqz"<<endl;
60         }
61         cout<<endl;
62         break;
63         }
64         p[sum[i]] = i ;
65     }
66     }
67   
68     return 0;
69 }
View Code