51Nod1103

Author Avatar
tkandi 10月 27, 2017
  • 在其它设备中阅读本文章

N的倍数

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

Description

一个长度为$N$的数组$A$,从$A$中选出若干个数,使得这些数的和是$N$的倍数。
例如:$N = 8$,数组$A$包括:$2 5 6 3 18 7 11 19$,可以选$2 6$,因为$2 + 6 = 8$,是$8$的倍数。

Input

第$1$行:$1$个数$N$,$N$为数组的长度,同时也是要求的倍数。($2 \le N \le 50000$)
第$2 - N + 1$行:数组$A$的元素。($0 \lt A[i] \le 10^9$)

Output

如果没有符合条件的组合,输出$No \ Solution$。
第$1$行:$1$个数$S$表示你所选择的数的数量。
第$2 - S + 1$行:每行$1$个数,对应你所选择的数。

Input示例

8
2
5
6
3
18
7
11
19

Output示例

2
2
6

Solution

我们记$sum_i = \sum_{j = 1}^i{a_j}$,若对于某个$i$,$sum_i$为$n$的倍数,那么原序列的$[1, i]$即为答案。否则,对于$sum_i \ (1 \le i \le n)$这$n$个数,因为它们模$n$的余数在$[1, n - 1]$范围内,所以肯定存在$i,j \ (1 \le i \lt j \le n)$满足$sum_i % n = sum_j% n $,那么原序列的$[i + 1, j]$即为答案。

Standard

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 50010;

int n;
int a[N], app[N];

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        sum = (sum + a[i]) % n;
        if (!sum) {
            printf("%d\n", i);
            for (int j = 1; j <= i; ++j)
                printf("%d\n", a[j]);
            return 0;
        }
        if (app[sum]) {
            printf("%d\n", i - app[sum]);
            for (int j = app[sum] + 1; j <= i; ++j)
                printf("%d\n", a[j]);
            return 0;
        }
        app[sum] = i;
    }
    puts("No Solution"); //tan 90°
    return 0;
}