Counting Subsequences | ||||||
| ||||||
Description | ||||||
"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 Output | ||||||
3 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
*/