哈理工oj 1005 Counting Subsequences

来源:互联网 发布:tina仿真软件视频教程 编辑:程序博客网 时间:2024/06/06 14:18

Counting SubsequencesTime Limit: 5000 MSMemory Limit: 65536 KTotal Submit: 905(280 users)Total Accepted: 253(219 users)Rating: Special Judge: NoDescription

 "47 is the quintessential random number," states the 47 society. And there might be a grain of truth in that.

For example, the first ten digits of the Euler's constant are:

2 7 1 8 2 8 1 8 2 8

And what's their sum? Of course, it is 47.

You are given a sequence S of integers we saw somewhere in the nature. Your task will be to compute how strongly does this sequence support the above claims.

We will call a continuous subsequence of S interesting if the sum of its terms is equal to 47.

E.g., consider the sequence S = (24, 17, 23, 24, 5, 47). Here we have two interesting continuous subsequences: the sequence (23, 24) and the sequence (47).

Given a sequence S, find the count of its interesting subsequences.

Input

The first line of the input file contains an integer T(T <= 10) specifying the number of test cases. Each test case is preceded by a blank line.

The first line of each test case contains the length of a sequence N(N <= 500000). The second line contains N space-separated integers – the elements of the sequence. Sum of any continuous subsequences will fit in 32 bit signed integers.

Output

For each test case output a single line containing a single integer – the count of interesting subsequences of the given sentence.

Sample Input
2
 
13
2 7 1 8 2 8 1 8 2 8 4 5 9
 
7
2 47 10047 47 1047 47 47
Sample Output3
4

题意:

看样例:给你一个数 T 表示接下来会有 T 组数据,每组数据有两行,第一行有一个数 n,表示接下来会有 n 个数,然后第二行就有 n 个数,题目要求你在这 n 个数中找出和为 47 的连续的数列的个数。


题解:

    这道题一开始我用二分法做,就是把所有的数边输入边用数组加起来,就像这样:输入第 i 个数arr,然后数组sum[i] = sum[i - 1] + arr;然后用二分法找数组sum 的下标 book,使得 sum[i] - sum[book] == 47,如果存在这样的下标,那么记录个数的变量 cnt++,但是这样有三个缺陷,一是变量 arr 可能是负数,这样数组 sum 就不是递增的了,二是数组有可能存不下这么多数,毕竟 N <= 500000,三是像数列:20 7 20 7 这样有两个  和  相同的连续子序列在加序列个数时有可能只加了其中的一个。

    然后就想出了如下思想:


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
///o(っ。Д。)っ AC万岁!!!!!!!!!!!!!!
const int maxn = 1000000, inf = -1999999999;
//int arr[maxn] = {};
map<int, int> maps;  ///用map存就不会爆内存了


int main()
{
    int _;
    scanf("%d", &_);
    while(_--)
    {
        maps.clear();
        maps[0] = 1;
        int n, sum = 0, book = 1, cnt = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n ;i++)
        {
            scanf("%d", &book);
            sum += book;   ///加上每一次输入的数
            maps[sum]++;  ///记录每一个连续子序列的和的个数
            cnt += maps[sum - 47];

            ///sum - 47 是为了查看是否存在一个连续子序列的和在加上紧接其后的和为 47 的另一个连续子序列之后即为本次子序列的和
        }
        printf("%d\n", cnt);
    }
}
/*
7
47 20 7 20 7 47 20
*/