Time Limit: 1000 ms Memory Limit: 65535 kB
Description
方方是一个调皮的孩子,每天到处搞破坏把妹子,邻居都讨厌他。一天方方不小心把邻居老姚神的魔法棒给摔成了n段,长度分别为a0,a1,……,an-1。方方虽然调皮,但还是不敢招惹可怕的老姚神,修复魔棒是如此的艰难,只能请求另一个邻居哈利波特大用魔法把魔棒修复,但哈利波特大正在忙着统计霍格沃茨的男女比例,没有太多时间帮方方修魔棒,只答应只为方方使用一次魔法。
哈利波特大的魔法很奇怪,魔法只能把一段连续的魔棒片段连在一起,并且连接的片段的长度之和必须为p的倍数,(例如n=6,p=11,a0到an-1分别为11,11,1,6,7,9,哈利波特大可以把a0和a1连在一起,或者把a3, a4, a5连在一起),注意老姚神的魔棒必须按顺序接,也就是说,方方不能随意改动a0, a1,... an-1的顺序。
方方想把尽可能多的魔法棒片段连在一起,现在想找你帮忙。
Input
第一行包含一个正数 T (T <= 50),表示数据组数。
接下来每组数据包含两行。
第一行包含两个整数 n, p (1<=n<=100000, 1<=p<=11),代表魔法棒有n段,连接的长度之和必须为p的倍数。
第二行包含n个正整数分别表示a0,a1……,a(n-1),(1 <= ai <= 1000, 0 <= i < n)。
Output
对于每组数据输出一行,表示能最多能连接起来的魔棒片段个数。.
Sample Input
5
6 11
11 11 1 6 7 9
1 2
1
1 3
3
10 2
1 2 3 4 5 6 7 8 9 10
4 3
1 2 3 4
Sample Output
3
1
1
9
3
Hint
注意在第二组样例中,事实上魔法根本无法施展,但是答案是1,因为即使不使用魔法,片段也是一个一个的~
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#define N 100005
const int P=15;
int a[N],sum; //定义 sum(第i个sum)= (a[1] + a[2] +... + a[i]) 称为i位置的前缀和。 (1 <= i <= n),特别的有sum[0] = 0。
int front[P]; //front[i]代表最小的下标x,使得sum[x] % P = i,rear[i]则代表最大的下标x满足相同的条件。枚举答案即可;
int rear[P];
int Max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int T,i,n,p;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&p);
sum=0;
for(i=0;i<p;i++)
{
front[i]=-1;
rear[i]=-1;
}
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
sum%=p; //sum代表前i个数的和对P取模的余数
if(front[sum]==-1)
front[sum]=i; //记录最先出现的满足条件下标i
rear[sum]=i; //记录最后出现的满足条件下标i
}
int ans=1;
for(i=0;i<p;i++)
if(front[i]!=-1&&rear[i]!=-1)
{
if(i==0)
ans=rear[i]+1; //余数为零下标加一就是答案!!
else
ans=Max(ans,rear[i]-front[i]);
}
printf("%d\n",ans);
}
return 0;
}