借鉴:
题意转化一下就是:
给出一列数a[1]...a[n],求长度最长的一段连续的数,使得这些数的和能被M整除。
分析:
设这列数前i项和为s[i],
则一段连续的数的和 a[i]+a[i+1]+...+a[j-1]+a[j]=s[j]-s[i-1],
所以这段连续的数的和能被m整除的条件就是 (s[j]-s[i-1]) % m == 0,
即 s[j]%m-s[i-1]%m == 0,
因此,只需要每一个余数找使s[i]%m等于该余数的最小的i,和s[j]%m等于该余数的最大的j,相减即为最长的连续的数的长度。
而M只有10000,余数比较小,方法可行。
Wrong key
c++好像不能用下标是负的数组,要把负数+M加成正的,我错了好久,拙计Add笨~
#include <iostream>
#include <stdio.h>
using namespace std;
int a[100001],s[100001],ans,i,j,n,m,l,f[10001][2];
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
ans=0;
memset(s,0,sizeof(s));
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
for (i=1;i<=n;i++)
{ s[i]=(s[i-1]+a[i])%m;
while (s[i]<0) s[i]+=m;
}
for (i=0;i<m;i++)
{
f[i][0]=1000000;
f[i][1]=-1000000;
}
for (i=0;i<=n;i++)
{
if (i<f[s[i]][0]) f[s[i]][0]=i;
if (i>f[s[i]][1]) f[s[i]][1]=i;
}
for (i=0;i<m;i++)
if ((f[i][1]-f[i][0])>ans)
ans=f[i][1]-f[i][0];
printf("%d\n",ans);
}
return 0;
}