1. 程式人生 > >糖果分發 - 抽屜原理

糖果分發 - 抽屜原理

brush targe ase eas CI sizeof sdn -c XP

推薦博客: https://blog.csdn.net/dingchenxixi/article/details/52459001 抽屜原理的一種更一般的表述為:
“把多於kn個東西任意分放進n個空抽屜(k是正整數),那麽一定有一個抽屜中放進了至少k+1個東西。 利用上述原理容易證明:“任意7個整數中,至少有3個數的兩兩之差是3的倍數。
”因為任一整數除以3時余數只有0、1、2三種可能,
所以7個整數中至少有3個數除以3所得余數相同,即它們兩兩之差是3的倍數。 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.


InputThe 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 a 1
, ... , a n (1 ≤ a i ≤ 100000 ), where a i represents the number of sweets the children get if they visit neighbour i.

The last test case is followed by two zeros.

OutputFor 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 a i
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

題意 : 從 m 個糖果袋裏選出任意數量的糖果袋,要求選出的糖袋中糖的數量是 n 的整數倍,輸出選出的糖袋。
思路分析:這題是抽屜原理一個非常好的應用,其實判斷選出的一些數能否被 n 整除,只需要看其余數能否整除 n即可,首先求一個前綴和,若存在余數為 0 的情況,則一定有答案。
  否則,則是兩個相同余數之間表示的區間是正確答案,根據抽屜原理,因為 n <= m,而 m 個數所構成的前綴和的余數有 1 - n-1, 共 n-1 個,因此一定存在兩個數他們的余數相同。
代碼示例:
#define ll long long
const int maxn = 1e5+5;

int n, m;
int pre[maxn], sum[maxn];
int p[maxn];

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    
    while(~scanf("%d%d", &n, &m) && n+m){
        memset(p, -1, sizeof(p));
        p[0] = 0;
        int s = -1, e = -1;
        for(int i = 1; i <= m; i++){
            scanf("%d", &pre[i]);
            sum[i] = (sum[i-1]+pre[i])%n;
            if (p[sum[i]] == -1) p[sum[i]] = i;
            else if (s == -1 && e == -1) s = p[sum[i]]+1, e = i;
        }
        for(int j = s; j <= e; j++){
            printf("%d%c", j, j==e?‘\n‘:‘ ‘);
        }
    }
    return 0;
}

糖果分發 - 抽屜原理