k倍区间

Posted TQCAI

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k倍区间相关的知识,希望对你有一定的参考价值。

用前缀和来求区间和,然后用一个二重循环穷举,但是因为问题规模为100000,所以超时(28分)

超时代码:

技术分享图片
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <string.h>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100010
#define MAX 0x06FFFFFF
#define V vector<int>
#define ll long long

using namespace std;

ll sum[LEN]; 

int main(){
//    freopen("D:/CbWorkspace/blue_bridge/k倍区间.txt","r",stdin);
    int i,j,n,k,ans=0;
    I("%d%d",&n,&k);
    FF(i,n){
        I("%d",&j);
        sum[i+1]=sum[i]+j;
    }
    for(i=1;i<=n;i++){
        for(j=i;j<=n;j++){
            int t=(sum[j]-sum[i-1]);
            if((sum[j]-sum[i-1])%k==0)
                ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}
View Code

观看了大佬的AC代码,终于明白怎么回事了。一句话, 计算前缀和然后取余k, 如果前i项和取余k与前j项和取余k后相同,那么i到j这个区间和为k的倍数

注意ans,cnt,sum都要开 long long

AC代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <string.h>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100010
#define MAX 0x06FFFFFF
#define V vector<int>
#define ll long long

using namespace std;

ll sum[LEN]; 
ll cnt[LEN];

int A(int n,int m){
    int a=1;
    while(m){
        a*=n--;
        m--;
    }
    return a;
}

int C(int n,int m){
    int c=A(n,m);
    while(m){
        c/=m--;
    }
    return c;
}

int main(){
//    freopen("D:/CbWorkspace/blue_bridge/k倍区间.txt","r",stdin);
    int i,j,n,k;
    ll ans=0;
    I("%d%d",&n,&k);
    FF(i,n){
        I("%d",&j);
        sum[i+1]=sum[i]+j;
    }
    cnt[0]=1;
    F(i,1,n+1){
        cnt[sum[i]%k]++;
    }
    FF(i,k){
        if(cnt[i]) ans+=cnt[i]*(cnt[i]-1)/2;    //C(n,2)
    }
    printf("%lld",ans);
    return 0;
}

 

以上是关于k倍区间的主要内容,如果未能解决你的问题,请参考以下文章

k倍区间

K倍区间

~~~k倍区间

第八届蓝桥杯-k倍区间

题集k倍区间(抽屉原理)

历届试题 k倍区间(需要用到前缀和!!!!!)