jzoj 2644. 数列

给你一个长度为N的正整数序列,如果一个连续的子序列,子序列的和能够被K整

除,那么就视此子序列合法,求原序列包括多少个合法的连续子序列?

对于一个长度为8的序列,K=4的情况:2, 1, 2, 1, 1, 2, 1, 2 。它的答案为6,子序列

是位置1->位置8,2->4,2->7,3->5,4->6,5->7。

Input

第一行:T,表示数据组数

对于每组数据:

第一行:2个数,K,N

第二行:N个数,表示这个序列

Output

共T行,每行一个数表示答案

 
简单数论加排序。。。
我们使用前缀和存储。(即从1到x的序列和)
然后,我们要找可以被k整除的区间和,
就存在S1 < S2
使满足S1≡S2(mod k)
根据同余,有
(S1-S2)≡0(mod k)
也就是,当S1和S2模k余数相等,就可以组成被k整除的区间。
可以把前缀和模k,然后排序,进行组合(不是高中那个,小学学的连线法就可以。。。)
或者用桶装起来,ans+=t*(t-1)/2
记住一定要把所有余数为0的单独加入ans,他很特殊
#include<bits/stdc++.h>
using namespace std;

int sum[50500],k,t,n;

int main(){
    scanf("%d",&t);
    for(int o=1;o<=t;o++){
        scanf("%d%d",&k,&n);
        sum[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&sum[i]);
            sum[i]=(sum[i]+sum[i-1])%k;
        }
        sort(sum+1,sum+1+n);
        int tt=0;
        sum[0]=-10086;
        int ans=0;
        for(int i=1;i<=n;i++){
            if(sum[i]==0)ans++;
            if(sum[i]==sum[i-1]){
                tt++;
                ans+=tt;
            }
            else tt=0;
        }
        printf("%d
",ans);
    }
    
    
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/you-xiao-mang-ci/p/11285360.html