HUST team contest #2 C Divisible Subsequences ||poj 3844 (剩余类)

Divisible Subsequences
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2326   Accepted: 843

Description

Given a sequence of positive integers, count all contiguous subsequences (sometimes called substrings, in contrast to subsequences, which may leave out elements) the sum of which is divisible by a given number. These subsequences may overlap. For example, the sequence (see sample input) 
2, 1, 2, 1, 1, 2, 1, 2

contains six contiguous subsequences the sum of which is divisible by four: the first to eighth number, the second to fourth number, the second to seventh number, the third to fifth number, the fourth to sixth number, and the fifth to seventh number.

Input

The first line of the input consists of an integer c (1 <= c <= 200), the number of test cases. Then follow two lines per test case. 
Each test case starts with a line consisting of two integers d (1 <= d <= 1 000 000) and n (1 <= n <= 50 000), the divisor of the sum of the subsequences and the length of the sequence, respectively. The second line of a test case contains the elements of the sequence, which are integers between 1 and 1 000 000 000, inclusively.

Output

For each test case, print a single line consisting of a single integer, the number of contiguous subsequences the sum of which is divisible by d.

Sample Input

2
7 3
1 2 3
4 8
2 1 2 1 1 2 1 2

Sample Output

0
6

Source

算是签到帖,竟然卡住了。

我数学还是太差了。。

然后去找题解。。竟然看不懂!

我数学真的有这么差嘛。。。

然后多亏了队友 @zcy 妹子的讲解。。

其实很好理解啊。。。

不过数到底还是数学太差了==

今天七夕,废话有点多==

这道题的题意是,找序列中连续的一段,使得和 可以整除d

我们观察到数列中的数的范围是1..1 000 000 000 的

而d只有1 000 000 

我们考虑余数相同,读入的时候就可以直接先 % 掉 d

因为只会和余数有关。

我们可以先处理出来一个前缀和数组sum[i],表示前i个元素的和。

如果有一段序列从a[i] 到 a[j] 满足题意

根据题意那么这段序列的和一定%d=0

a[i] 到 a[j]的和为 sum[j]-sum[i-1]

也就是(sum[j]-sum[i-1] )%d==0

也就是sum[j] 和 sum[i-1] 关于 d 同余

如果我们在处理得到前缀和的时候就%d

那么就是sum[j]==sum[i-1]

所以我只要对于d的每一个剩余类有多少个统计出来。

然后对于每个剩余类,只需要任意取出两个,就是一种答案。

需要注意的是如果只有一个0,也是一种答案。

我们可以定义sum[i] = 0

还有一个需要注意的是要开long long

/*************************************************************************
    > File Name: code/2015summer/0821.cpp
    > Author: 111qqz
    > Email: rkz2013@126.com 
    > Created Time: 2015年08月20日 星期四 23时45分20秒
 ************************************************************************/

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#define y0 abc111qqz
#define y1 hust111qqz
#define yn hez111qqz
#define j1 cute111qqz
#define tm crazy111qqz
#define lr dying111qqz
using namespace std;
#define REP(i, n) for (int i=0;i<int(n);++i)  
typedef long long LL;
typedef unsigned long long ULL;
const int inf = 0x7fffffff;
const int N=1E6+7;
int sum[50005];
LL p[N];

void solve ()
{
    int d,n;
    int x;
    memset(p,0,sizeof(p));
    sum[0] =  0;
    p [0] = 1;
    scanf("%d %d",&d,&n);
    for ( int i = 1 ; i <= n ; i++){
    scanf("%d",&x);
    sum[i] = (sum[i-1] + x) % d;
    p[sum[i]]++;
    }
    LL ans = 0 ;
    for ( int i = 0 ; i < d ; i++){
//    cout<<p[i]<<endl;
    if (p[i]>0){
        ans = ans + p[i]*(p[i]-1)/2;
    }
    }
    cout<<ans<<endl;
}
int main()
{
    int T;
    cin>>T;
    while (T--){
    solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/111qqz/p/4746665.html