51nod 2518 和为S
原创
©著作权归作者所有:来自51CTO博客作者mb5f5b1df7f1e34的原创作品,请联系作者获取转载授权,否则将追究法律责任
小b有一个01序列A,她想知道A有多少个非空连续子序列和为S。
你能帮帮她吗?
收起
输入
第一行输入一个数n,表示A的长度;
第二行输入n个数‘0’或‘1’,表示A中的元素,以空格隔开;
第三行输入一个非负整数S;
其中0≤S≤n≤30000。
输出
输出一个数,表示子数组的个数
输入样例
5
1 0 1 0 1
2
输出样例
4
分析:
sum[r]-sum[l-1]==k,则对于每一个sum[i]统计其前面k-sum[i]的个数即可,注意最后加上sum[i]==k的情况。
扩展:
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
你能求出数列中总共有多少个K倍区间吗?
求区间[l,r]的和是k的倍数的个数。区间[l,r]的和是k的倍数即(sum[r] - sum[l-1])%k == 0 即sum[r]%k == sum[l-1]%k,即对于每一个sum[i]求sum[i]%k的个数即可,注意最后加上map[0]的情况
import java.util.HashMap;
import java.util.Scanner;
public class Main {
static Long [] x=new Long[30005];
static Long [] sum=new Long[30005];
static Long [] dp=new Long[505];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
sum[0]=(long) 0;
HashMap<Long,Integer> map=new HashMap<>();
for(int i=1;i<=n;i++)
{
x[i]=in.nextLong();
}
Long k=in.nextLong();
Long ans=(long) 0;
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+x[i];
if(sum[i]==k)
{
ans++;
}
if(map.containsKey(sum[i]-k)==true)
{
ans+=map.get(sum[i]-k);
}
if(map.containsKey(sum[i]))
{
map.replace(sum[i], map.get(sum[i])+1);
}
else map.put(sum[i], 1);
}
System.out.println(ans);
System.gc();
}
}