题目大意 有一个环,环上有一些数,求分成i份,每份要连续,对于每个分成i份的情况求每一份的数的和gcd起来最大是多少。 解题思路 我们发现答案一定是所有数和的约数,这不会很大,找出约数后求模约数的前缀和,有多少个相同就可以分成多少份。 code #include<cmath> #include<cstdio> #include<algorithm> #define LF double #define LL long long #define min(a,b) ((a<b)?a:b) #define max(a,b) ((a>b)?a:b) #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) using namespace std; int const maxn=2000,size=50000; int n;LL s[maxn+10],b[10],ans[maxn+10],h[size+10],cnt[size+10],pos[maxn+10]; int hash(LL x){ int pos=x%size; for(;h[pos]&&(h[pos]!=x);pos=(pos==size-1)?0:pos+1); return pos; } int main(){ freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d",&n);int a; fo(i,1,n)scanf("%d",&a),s[i]=s[i-1]+a; int mx=sqrt(s[n]); fo(i,1,mx) if(s[n]%i==0){ b[1]=i;b[2]=s[n]/i; fo(ii,1,2){ fo(j,1,n){ pos[j]=hash(s[j]%b[ii]); h[pos[j]]=s[j]%b[ii]; cnt[pos[j]]++; ans[cnt[pos[j]]]=max(ans[cnt[pos[j]]],b[ii]); } fo(j,1,n)h[pos[j]]=cnt[pos[j]]=0; } } fo(i,1,n)printf("%lld\n",ans[i]); return 0; }