題目是說給你N個數再給一個MOD 這N個數的和對MOD取模的值是K問你可以從這N個數中最多刪除多少個連續的數使得剩下的數的和模上MOD的結果不變還是K
這題數據范圍有點大,不過有O(N)的算法就可以搞定了。
方法 題意轉化一下就是: 給出一列數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,相減即為最長的連續的數的長度。
代碼就比較簡單了,只要記錄最先出現的不同和得下標就可以很快做出來的,代碼精簡了sum數組和原數據的數組,可能會有點難懂。。其中v數組的應用是關鍵,挺好的,這個方法
#include<stdio.h>
#include<string.h>
inline int max(int a,int b) {return a>b? a:b;}
int N,M,a,v[10005],ans,sum,i,pre;//pre是用來記錄sum[i-1]的而sum記錄的是sum[i]
// v數組的v[i]記錄的是第一次出現前綴和為i時其對應的下標,若沒出現過就是-1
int main()
{
while(~scanf("%d%d",&N,&M))
{
memset(v,-1,sizeof(v));
pre=v[0]=sum=ans=0;
for(i=1;i<=N;++i)
{
scanf("%d",&a);
sum=(pre+a)%M;
sum=(sum+M)%M;//因為有負數,取模的時候要注意一下的
if(v[sum]==-1) v[sum]=i;
ans=max(ans,i-v[pre=sum]);
}
printf("%d\n",ans);
}
return 0;
}