题目
题目描述
小A
有一个环,环上有
n
n
n个正整数
他有特殊的能力(???),能将环切成
k
k
k段,每段包含一个或者多个数字
对于一个切分方案,小A
将以如下方式计算优美程度:
首先对于每一段,求出他们的数字和
然后对于每段的和,求出他们的最大公约数,即为优美程度
他想通过合理地使用他的特殊能力,使得切分方案的优美程度最大
输入格式
第一行一个整数
n
n
n,表示环上的数字个数
接下来一行包含
n
n
n个正整数,第
i
i
i个数
a
i
a_i
ai表示环上第
i
i
i个数
输出格式
输出 n n n行,第 i i i行表示切成 i i i段时的最大优美程度
样例
样例输入
7
2 3 3 3 3 3 3
样例输出
20
5
2
2
1
1
1
数据范围与提示
对于
20
%
20\%
20%的数据,
n
⩽
16
,
a
i
⩽
10
n \leqslant 16,a_i \leqslant 10
n⩽16,ai⩽10
对于
40
%
40\%
40%的数据,
n
⩽
100
,
a
i
⩽
1000
n \leqslant 100,a_i \leqslant 1000
n⩽100,ai⩽1000
对于
100
%
100\%
100%的数据,
n
⩽
2000
,
1
⩽
a
i
⩽
5
×
1
0
7
n \leqslant 2000,1 \leqslant a_i \leqslant 5 \times 10^7
n⩽2000,1⩽ai⩽5×107
题解
显然,答案是
∑
i
=
1
n
a
i
\sum \limits_{i=1}^na_i
i=1∑nai的约数
所以我们可以枚举
∑
i
=
1
n
a
i
\sum \limits_{i=1}^na_i
i=1∑nai的每一个约数,对于每一个约数
d
d
d,计算最多能切成几段,使得这几段
g
c
d
gcd
gcd起来是
d
d
d
现在的问题就是到底能分成几段
这个非常简单
我们统计前缀和
s
u
m
i
sum_i
sumi,如果
s
u
m
i
≡
s
u
m
j
(
m
o
d
d
)
sum_i\equiv sum_j\pmod{d}
sumi≡sumj(modd),那么
i
∼
j
i\sim j
i∼j就可以分一段
所以,我们可以用一个map统计
s
u
m
i
sum_i
sumi模
d
d
d的余数,然后答案就是这个map中值最大的那个
最终的答案就是后缀最大值啦!
附上代码:
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
int n;
long long a[2010],ans[2010];
map<long long,int> mod;
void work(long long k)
{
mod.clear();
for(int i=1,s;i<=n;i++) s=++mod[a[i]%k],ans[s]=max(ans[s],k);
}
int main()
{
freopen("circle.in","r",stdin);
freopen("circle.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]+=a[i-1];
for(long long i=1;i<=sqrt(a[n]);i++) if(!(a[n]%i)){
work(i);
if(i*i!=a[n]) work(a[n]/i);
}
for(int i=n;i;i--) ans[i]=max(ans[i],ans[i+1]);
for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
}