zoukankan      html  css  js  c++  java
  • 【题集】k倍区间(抽屉原理)

    例1:http://lx.lanqiao.cn/problem.page?gpid=T444

    蓝桥杯
    问题描述
      给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
      你能求出数列中总共有多少个K倍区间吗?
    输入格式
      第一行包含两个整数N和K。(1 <= N, K <= 100000)
      以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
    输出格式
      输出一个整数,代表K倍区间的数目。
    分析:
    1、因为(sum[r] - sum[l-1]) % k == 0,可推出sum[r] % k == sum[l - 1] % k.
    2、因此,将前缀和分别对K取模。
    3、分别统计出取模后的各数字的个数。
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = 100000 + 10;
    int sum[MAXN];
    int cnt[MAXN];
    int main(){
        int N, K;
        scanf("%d%d", &N, &K);
        for(int i = 0; i < N; ++i){
            scanf("%d", &sum[i]);
        }
        sum[0] %= K;
        for(int i = 1; i < N; ++i){
            sum[i] = ((sum[i] % K) + sum[i - 1]) % K;
        }
        LL ans = 0;
        for(int i = 0; i < N; ++i){
            ans += cnt[sum[i]]++;
        }
        printf("%lld
    ", ans + cnt[0]);
        return 0;
    }
    

    例2:https://cn.vjudge.net/problem/POJ-3370

    题意:每个邻居可以给ai个糖,共n个邻居,问向哪几个邻居要糖可以正好被c个孩子平分。

    分析:此题和例1解法相似。

    若sum[i] % c == 0,则[1, i]可以被c整除;

    若sum[l - 1] % c == sum[r] % c,则[l, r]可以被c整除;

    由于输出任意一种答案即可,那会不会存在一种可能,就是答案都不是连续的区间,而是不连续的区间呢?

    由于本题中c<=n,因此一定存在连续区间的解。

    原因在于,

    若sum[i]能被c整除,一定存在连续区间的解[1, i];

    若sum[i]不能被c整除,则sum[i]%c可能的结果在[1, c-1]里,共c-1种可能,而c-1<n,根据抽屉原理,因此一定存在一对i, j,使得sum[i] % c == sum[j] % c,即存在连续区间解[i + 1, j].

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int MAXN = 100000 + 10;
    int sum[MAXN];
    int id[MAXN];
    int main(){
        int c, n;
        while(scanf("%d%d", &c, &n) == 2){
            if(!c && !n) return 0;
            memset(sum, 0, sizeof sum);
            memset(id, 0, sizeof id);
            for(int i = 1; i <= n; ++i){
                scanf("%d", &sum[i]);
            }
            sum[1] %= c;
            for(int i = 2; i <= n; ++i){
                sum[i] = ((sum[i] % c) + sum[i - 1]) % c;
            }
            int st, et;
            for(int i = 1; i <= n; ++i){
                if(sum[i] == 0){
                    st = 1;
                    et = i;
                    break;
                }
                if(id[sum[i]]){
                    st = id[sum[i]] + 1;
                    et = i;
                    break;
                }
                id[sum[i]] = i;
            }
            for(int i = st; i <= et; ++i){
                printf("%d", i);
                if(i == et) printf("
    ");
                else printf(" ");
            }
        }
        return 0;
    }
    

    例3:https://cn.vjudge.net/problem/POJ-2356

    分析:与例2相似,因为N-1 < N,所以一定存在连续区间的解。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    const int MAXN = 15000 + 10;
    int a[MAXN];
    int sum[MAXN];
    int id[MAXN];
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
        }
        sum[1] = a[1] % n;
        for(int i = 2; i <= n; ++i){
            sum[i] = ((a[i] % n) + sum[i - 1]) % n;
        }
        int st, et;
        for(int i = 1; i <= n; ++i){
            if(sum[i] == 0){
                st = 1;
                et = i;
                break;
            }
            if(id[sum[i]]){
                st = id[sum[i]] + 1;
                et = i;
                break;
            }
            id[sum[i]] = i;
        }
        printf("%d
    ", et - st + 1);
        for(int i = st; i <= et; ++i){
            printf("%d
    ", a[i]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    设计模式
    包装类
    php 闭包的理解
    is_null empty isset等的判定
    PHP基础一 $this ,static 和 self的区别
    lumen安装踩过得坑
    composer的使用和安装
    使用submine来写c++
    php 和 thinkphp中的常量一览
    路径问题 ./ / ../ 空 的区别
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/8454521.html
Copyright © 2011-2022 走看看