给你一个长度为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。
简单数论加排序。。。
我们使用前缀和存储。(即从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; }