HDUOJ 6794 Tokitsukaze and Multiple

HDUOJ 6794 Tokitsukaze and Multiple

题目链接

Problem Description

Tokitsukaze has a sequence of length n, denoted by a.

Tokitsukaze can merge two consecutive elements of a as many times as she wants. After each operation, a new element that equals to the sum of the two old elements will replace them, and thus the length of a will be reduced by 1.

Tokitsukaze wants to know the maximum possible number of elements that are multiples of p she can get after doing some operations (or doing nothing) on the sequence a.

Input

There are several test cases.

The first line contains an integer T (1≤T≤20), denoting the number of test cases. Then follow all the test cases.

For each test case, the first line contains two integers n and p (1≤n,p≤1e5), denoting the length of the sequence and the special number, respectively.

The second line contains n integers, where the i-th integer ai (1≤ai≤1e5) is the i-th element of a.

It is guaranteed that the sum of n in all test cases is no larger than 1e6.

Output

For each test case, output in one line the maximum possible number of elements that are multiples of p after doing some operations.

Sample Input

2
5 3
2 1 3 2 1
3 1
123 456 789

Sample Output

3
3

这题就题意比较难懂,看懂了就发现很简单了~
字面理解就是你可以选择操作任意次,使得最后这个序列中是 p p p 倍数的元素个数最大,题解有更好的解释:把序列切分成若干段,然后看看有几段的和是 p 的倍数~
这是典型的前缀和问题,我们先预处理出前缀和,当有两个前缀和相等时,这段区间和就一定是 p p p 的倍数,注意当前缀和刚好为 p p p 的倍数时答案也要加 1 1 1,AC代码如下:

#include
using namespace std;
typedef long long ll;
const int N=1e5+5;
int a[N],sum[N];
int main(){
    int t,n,p;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=(a[i]+sum[i-1])%p;
        map<int,int>m;
        int ans=0;
        m[0]=1;
        for(int i=1;i<=n;i++){
            if(m[sum[i]]){
                ans++;
                m.clear();
            }
            m[sum[i]]=1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(前后缀和,map,HDUOJ)