题意:
给出一个序列,问子序列是k的倍数的个数。
题解:
用hash存0-n的前缀和,然后根据这个式子 (sum[j]-sum[i])%k=0 变形 (sum[j]%k+k)%k=(sum[i]%k+k)%k ,这样做为了保证负数也通过。然后只要查找是否目前hash中能找到多少个(sum[j]%k+k)%k。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
void cmax(int& a,int b){if(b>a)a=b;}
void cmin(int& a,int b){if(b<a)a=b;}
void lcmax(ll& a,ll b){if(b>a)a=b;}
void lcmin(ll& a,ll b){if(b<a)a=b;}
const int oo=0x3f3f3f3f;
const int MOD=1000007;
const int maxn=1000007;
struct HASH_MAP{
ll state[maxn],num[maxn];
int next[maxn],head[maxn],tol;
void Init(){
memset(head,-1,sizeof head);
tol=0;
}
ll check(ll s){
ll ans=0;
int h=(s%maxn+maxn)%maxn;
for(int i=head[h];i!=-1;i=next[i]){
if(s==state[i]){
num[i]++;
ans+=num[i];
}
}
return ans;
}
void ins(ll s){
int h=(s%maxn+maxn)%maxn;
for(int i=head[h];i!=-1;i=next[i]){
if(s==state[i])return;
}
state[tol]=s;
num[tol]=0;
next[tol]=head[h];
head[h]=tol++;
}
}mat;
int main(){
//freopen("E:\\read.txt","r",stdin);
int T,n,k,a;
scanf("%d",&T);
while(T--){
mat.Init();
scanf("%d %d",&n,&k);
ll sum=0;
ll ans=0;
mat.ins(0);
for(int i=1;i<=n;i++){
scanf("%d",&a);
sum+=a;
ans+=mat.check((sum%k+k)%k);
mat.ins((sum%k+k)%k);
}
printf("%lld\n",ans);
}
return 0;
}