您的位置:首页 > 其它

SDUT3173 有多少个连续子序列的和能被k整除

2016-02-02 14:25 309 查看

题目描述

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
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=3173
范围很大不能用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 longusing 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;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: