• 51nod 1103 N的倍数 (鸽巢原理)


    题目来源: Ural 1302
    基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
     收藏
     关注
    一个长度为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 <= N <= 50000)
    第2 - N + 1行:数组A的元素。(0 < A[i] <= 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

    令i的前缀和%n为sum
    如果sum=0,则输出1到i的数
    用数组b[i][]记录前缀和%n=i的数有几个、分别是谁
    由鸽巢原理可得,在没有sum=0的情况下,
    所有的前缀和%n的结果一定有相同的数
    (n-1种情况,n个前缀和)
    所以本题一定有解
    若a、b的前缀和%n相同
    那么a+1到b之间的数的和为n的倍数
    #include<cstdio>
    #define N 50001
    using namespace std;
    int a[N],sum[N];
    int n;
    int b[N][3];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=(sum[i-1]+a[i])%n;
            if(!sum[i])
            {
                printf("%d
    ",i);
                for(int j=1;j<=i;j++) printf("%d
    ",a[j]);
                return 0;
            }
            b[sum[i]][++b[sum[i]][0]]=i;
            if(b[sum[i]][0]>1)
              {
                  printf("%d
    ",b[sum[i]][2]-b[sum[i]][1]); 
                for(int j=b[sum[i]][1]+1;j<=b[sum[i]][2];j++)
                        printf("%d
    ",a[j]);
                    return 0;
              }
        }
    }
  • 相关阅读:
    WPF笔记(1)
    Java笔记(3)
    Java笔记(2)
    Java笔记(1)
    PHP学习笔记(5)
    PHP学习笔记(4)
    PHP学习笔记(3)
    PHP学习笔记(2)
    PHP学习笔记(1)
    WKWebView 支持https请求
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6718241.html
Copyright © 2020-2023  润新知