题目
题目大意是给定n个数字的序列,可以任意合并其中相邻的数字,使他们相加,问最多能有多少个p的倍数。
贪心
这个题可以使用贪心的写法来解决。首先p的倍数这种事情重点只有余数部分,所以先对所有数字取模,且每次相加都要取模。只需要关心最终能搞出几个零就行了。
可以直接遍历整个数组,加上新来的数字,如果加上后这个余数在前面出现过则证明以该数字位结尾的一段数字加和是p的倍数,统计入答案,并重置标记数组。重复这个过程即可。
另外,对于重置标记数组,如果每次都循环置零,那么就会超时,可以使用一个小技巧,使用一个cnt
变量来进行标记,这样每次需要重置标记数组时,就不需要置零,只需要改变cnt
到一个未出现过的值即可,通常让其++;
代码:
#include<iostream>
#include<cstdio>
#define N 100050
using namespace std;
int a[N];
int vis[N];
int p,n,T,cnt = 0,ans;
int main(){
for(cin >> T;T;T--){
scanf("%d%d",&n,&p);
ans = 0;
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
a[i] %= p;
}
cnt++;
int sum = 0;
for(int i = 1;i <= n;i++){
sum += a[i];
sum %= p;
if(vis[sum] == cnt || sum == 0){
ans++;
sum = 0;
cnt++;
continue;
}
vis[sum] = cnt;
}
printf("%d\n",ans);
}
}