SDUT3173 有多少個連續子序列的和能被k整除
阿新 • • 發佈:2019-02-04
題目描述
Edward 得到了一個長度為 N 的整數序列,他想找出這裡面有多少個“幸運的”連續子序列。一個連續子序列被稱為“幸運的”,當且僅當該子序列內的整數之和恰好是 K 的整數倍數。他請求你寫一個程式來計算他喜歡的連續子序列個數。輸入
輸入第一行是一個整數 T,表示有 T 組資料。 每組資料第一行是兩個整數 N (1 <= N <= 10^6 ), K (1 <= K <= 10^9 )。 接下來的一行包含 N 個整數 A i (|A i | <= 10^9 )。輸出
對於每組測試資料,輸出一行僅包含一個整數,表示 Edward 喜歡的連續子序列數量。示例輸入
2 5 3 1 2 3 4 1 6 2 1 2 1 2 1 2
示例輸出
4 9
範圍很大不能用O(n2)的做法。這時考慮字首和同模做差。但是很難想到。
比如,有a b c d e,(a+b)%mod=k,(a+b+c+d+e)%mod也=k,那麼(c+d+e)%mod=0,即該子序列是mod的整數倍數。
#include<iostream> #include<algorithm> #include<string> #include<map> #include<cmath> #include<string.h> #include<stdlib.h> #include<cstdio> #define ll long long using namespace std; ll x[1000001]; ll C(ll m,ll n){ ll i,j,sum=1; for (i=m,j=0;j<n;j++,i--) sum=sum*i/(j+1); return sum; } int main(){ ll t,n,m; scanf("%lld",&t); while(t--){ scanf("%lld%lld",&n,&m); x[0]=0; ll cnt=0; ll w; for(ll i=1;i<=n;++i){ cin>>w; x[i]=((x[i-1]+w)%m+m)%m; //因為w有可能是負的 } sort(x,x+n+1); ll s=1; for(ll i=1;i<=n;++i){ if(x[i]==x[i-1]) s++; else{ cnt+=C(s,2); s=1; } } cnt+=C(s,2); printf("%lld\n",cnt); } return 0; }