POJ 2356 Find a multiple

来源:互联网 发布:淘宝客活动报名审核 编辑:程序博客网 时间:2024/06/01 09:34

**

Description:

给出n(n<=10000)个数,任选q其中几个数,使其和为n的倍数。

Input:

输入的第一行包含一个数字n,接下来的n行每一行包含一个给定集合中的一个数字。

Output:

如果你的程序决定找不到目标的数字集,它应该输出到单个数字0。否则,它应该在第一行中打印所选数字的数目,然后按任意顺序打印所选数字(每一行上的每一行)。如果有多个具有所需属性的数字集,那么只需输出一个。

分析:
题目是special judge,只要找到即可。设前k项和Sk表示a1+a2+……ak, 如果Sk是n的倍数,那就直接取Sk,否则S1-Sn % n分布在1 –(n-1)然后判断这些数能否整除n,如果能则输出下标,然后直接从第一个数开始依次输出即可,否则就根据抽屉原理 ( 把多于n个的物体放到n个抽屉里,则至少有一个抽屉里有>=2个以上的物体 )得: n个 sum【i】% n中,至少有两个是一样的。(因此,此题一定有解,不存在输出0的情况)如果找到,则说明sum[i] % n == sum[j] %n 即sum[j] - sum[i])%n==0。也就是 夹在 i j 之间的数的和是 n的倍数,只要依次将他们输出就可以了。

所用知识:抽屉原理(组合数学)

题解:
只需要算出S1、S2、……Sk ,然后对n取余,如果没有取余后为0的,按sum[j] - sum[i])% n ==0 的公式算出 i , j,然后输出i 到 j的元素即可。

程序思路:
- 用Node结构体存储节点信息,之后按题解思路编写代码
这里写图片描述

AC C++代码 (POJ):
//————————————————-

#include <iostream>using namespace std;#define MAX 10010struct Node{    int a; //当前元素取值    int sum;//前k项和}node[MAX];bool mod[MAX];//利用哈希表,快速找出数组中相同的取余void print(size_t first, size_t last){    cout << last - first + 1 << endl;    for(size_t i(first);i<=last;++i)        cout << node[i].a << endl;}void memsetMod(size_t &n){    for (size_t i = 0; i < n; ++i)        mod[i] = false;}int main(){    size_t n(0),i(0);    bool flag(false);    node[0].sum = 0;    while(cin>>n)    {               memsetMod(n);//初始化Mod数组        for(i = 1;i <= n;++i)        {            cin >> node[i].a;            if (flag) continue;//如果flag为true表示已经输出了结果,只需要把剩余数据接收就行,不需要再运算            node[i].sum = node[i].a + node[i-1].sum;            size_t modCopy = node[i].sum % n;//S[i] % n的余数            if (modCopy == 0){//如果刚好有n的倍数                print(1, i);//输出                flag = true;            }            else if (mod[modCopy]) {//利用哈希数组快速找出Mod数组中相同元素                print(modCopy + 1, i);                flag = true;            }            else mod[modCopy] = true;        }    }    return 0;}
原创粉丝点击