sum HDU

来源:互联网 发布:全看网软件下载 编辑:程序博客网 时间:2024/05/23 02:05

sum

HDU-5776
Given a sequence, you’re asked whether there exists a consecutive subsequence whose sum is divisible by m. output YES, otherwise output NO

Input
The first line of the input has an integer T (1≤T≤101≤T≤10), which represents the number of test cases.
For each test case, there are two lines:
1.The first line contains two positive integers n, m (1≤n≤1000001≤n≤100000, 1≤m≤50001≤m≤5000).
2.The second line contains n positive integers x (1≤x≤1001≤x≤100) according to the sequence.

Output
Output T lines, each line print a YES or NO.

Sample Input
2
3 3
1 2 3
5 7
6 6 6 6 6

Sample Output
YES
NO

先简单的 说一下 题意,就是 给你一个 序列 包含 n 个 整数, 给你一个 m 让你 判断 该序列 中 是否 存在 这一段 连续的 序列 其中的 整数 和 可以被 m 整除。这道题呢 是我 在 做 尺取法 专题训练的时候 做的,但是 尺取法 会WA 的,仔细想了想明白了 为什么 不能用尺取法了:尺取法呢 大概是应用于这么一类 题:给你一个 序列,让你 查询 不大于 某个数 的 连续序列的最大长度(即最优连续子序列), 或者 让你查询,大于某一个数的 连续序列的 最小长度 (最优连续自序列),而这道题呢,明显不是 上面 说的两种 情况。这道题呢 使用 抽屉原理来 解决的,下面先简单说一下什么是抽屉原理.

抽屉原理:如果现在有3个苹果,放进2个抽屉,那么至少有一个抽屉里面会有两个苹果。 这个 例子呢 本题 不是 太 贴切 ,我在举一个例子:假如说 有 三种 颜色的 玻璃球 颜色分别为 red yellow blue 这里 有 三个 颜色的 盒子 也是 red yellow blue ,箱子是空的 ,现在 给你 四个 小球 ,你从 装有 三种颜色玻璃球的 袋子中 随机拿出来四个 小球 ,然后 分别将他们放入 相同颜色的盒子中,然后你会发现 总会 有一个 盒子 里面 会出现 多个 玻璃球的 ,这个 就是 抽屉原理, 其实 呢 这个抽屉原理 的概念很简单,就是 生活中 很常见的 现象 或者 说事实, 但是 在 证明类 问题上 它的 解题思想 对于 运用反证法解题 很有帮助。
抽屉原理的运用

现在假设有一个正整数序列a1,a2,a3,a4…..an,试证明我们一定能够找到一段连续的序列和,让这个和是n的倍数,该命题的证明就用到了抽屉原理

我们可以先构造一个序列si=a1+a2+…ai

然后分别对于si取模,如果其中有一个sk%n==0,那么a1+a2+…+ak就一定是n的倍数(该种情况得证)

下面是上一种情况的反面,即任何一个sk对于n的余数都不为0

对于这种情况,我们可以如下考虑,因为si%n!=0

那么si%n的范围必然在1——(n-1),所以原序列si就产生了n个范围在1——(n-1)的余数,于是抽屉原理就来了,n个数放进n-1个盒子里面,必然至少有两个余数会重复,那么这两个sk1,sk2之差必然是n的倍数,

而sk1-sk2是一段连续的序列,那么原命题就得到了证明了

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int main(){    int t;    scanf("%d", &t);    while(t--)    {        int n, m, sum, num, flag = 0;        bool vis[5005];        scanf("%d%d", &n, &m);        memset(vis, false, sizeof(vis));        sum = 0;        vis[0] = 1;// 这个 如果不写的 会 WA 的 因为 如果出现 sum可以被 m  整除的话 就不运用 抽屉原理 直接就是 YES 啦         for(int i = 1; i <= n; i++)        {            scanf("%d", &num);            sum += num;            if(vis[sum%m]) flag = 1;            vis[sum%m] = true;        }        if(flag)            printf("YES\n");        else            printf("NO\n");    }    return 0;}