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≤105), 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≤105) is the i-th element of a.
It is guaranteed that the sum of n in all test cases is no larger than 106.
Output
For each test case, output in one line the maximum possible number of elements that are multiples of p after doing some operations.
样例输入
在这里插入代码片
2
5 3
2 1 3 2 1
3 1
123 456 789
样例输出
3
3
思路:
对输入的每个数对p取余,遍历数组,记录前面相加出现的结果,如果后面相加出现的结果x之前出现过,则前面出现x的位置到当前位置这个区间的和对p求余为0. 尽可能选择最先满足区间和对p取余的结果为0的区间,这样求出来的是最大的,如果区间的和为p倍数且其中的后缀跟后缀的后面几个数相加起来等于p的倍数,则应该选该区间而不是后面的那个区间,因为选择前面区间可以给后面的数字更多等于p的倍数的机会。
代码:
在这里插入代码片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[100001];
int vis[100001];
int cnt = 0,ans;
int main()
{
ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
int t;
cin>>t;
while(t--){
int n,p;
cin>>n>>p;
ans = 0;
for(int i = 1;i <= n;i++){
cin>>a[i];
a[i]=a[i]%p;
}
cnt++;
ll sum = 0;
//用cnt来区别是否是已经消去了的区间
//a...b...c...d
//假设ab区间内相加的和为p的倍数且里面的前缀和用vis记录且设为1
//消去之后如果cnt没有+1,则后面ad区间中的某一段包括ab部分和cd中的一部分加起来为p的倍数
//但是之前消去了就会导致误认为没消去 如果cnt不加1的话
for(int i = 1;i <= n;i++){
sum += a[i];
sum %= p;
if(vis[sum] == cnt || sum == 0){
ans++;
sum = 0;
cnt++;
}
else
vis[sum] = cnt;
}
cout<<ans<<endl;
}
}