#1246 : 王胖浩與環
描述
王胖浩有一個環,環上有n個正整數。他有特殊的能力,能將環切成k段,每段包含一個或者多個數字。
對於一個切分方案,王胖浩將以如下方式計算優美程度,
首先對於每一段,求出他們的數字和。然後對於每段的和,求出他們的最大公約數,即爲優美程度。
他想通過合理地使用他的特殊能力,使得切分方案的優美程度最大。
輸入
第一行一個整數n,表示環上的數字個數。
接下來一行包含n個正整數,第i個數ai表示環上第i個數。
數據範圍:
1<=n<=2000,1<=ai<=5*107
輸出
輸出n行,第i行表示切成i段時的最大優美程度。
7 2 3 3 3 3 3 3樣例輸出
20 5 2 2 1 1 1
又學到了新姿勢。。。一堆數的公共約數,實際上一定在 這堆數和 的約數裏面找。因爲很簡單的道理,a%x=0 b%x=0,(a+b)是肯定%x=0的。
然後就是將約數從大到小排序,看它們在前綴和裏面出現的次數,這裏的做法也感覺太亮了。果然自己做題還是太少了啊。。。
代碼:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <map>
#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
ll n;
ll val[2005];
ll num[5000];
ll ans[2005];
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
ll i, j, nu;
scanf("%lld", &n);
val[0] = 0;
for (i = 1; i <= n; i++)
{
scanf("%lld", val + i);
val[i] = val[i - 1] + val[i];
}
sort(val + 1, val + n + 1);
nu = 0;
for (i = 1; i *i <= val[n]; i++)
{
if (val[n] % i==0)
{
if (i*i == val[n])
{
num[nu++] = i;
continue;
}
num[nu++] = i;
num[nu++] = val[n] / i;
}
}
sort(num, num + nu);
ll temp, k, m;
k = 1;
for (i = nu - 1; i >= 0; i--)
{
temp = num[i];
map<ll, ll>cnt;
m = 0;
for (j = 1; j <= n; j++)
{
m = max(m, ++cnt[val[j] % temp]);
}
while (k <= m)
{
ans[k] = temp;
k++;
}
}
for (i = 1; i <= n; i++)
{
printf("%lld\n", ans[i]);
}
//system("pause");
return 0;
}