/*
问题描述
石子游戏的规则如下:
地上有n堆石子,每次操作可选取两堆石子(石子个数分别为x和y)并将它们合并,
操作的得分记为(x+1)×(y+1),对地上的石子堆进行操作直到只剩下一堆石子时停止游戏。
请问在整个游戏过程中操作的总得分的最大值是多少?
输入格式
输入数据的第一行为整数n,表示地上的石子堆数;第二行至第n+1行是每堆石子的个数。
输出格式
程序输出一行,为游戏总得分的最大值。
样例输入
10
5105
19400
27309
19892
27814
25129
19272
12517
25419
4053
样例输出
15212676150
15212676150
数据规模和约定
1≤n≤1000,1≤一堆中石子数≤50000
*/
使用贪心
先用归纳法证明一下正确性 发现可用long long 就足够了
好比一个具体的数列 1 2 3
使其一般化 即设数列 a1 a2 a3 ,
其中 a1 是 1 2 3 当中的任意一个数 a2 是 1 2 3 中除了a1的任意的一个数 那么a3就是剩下的最后的一个数
这样我们即使从前往后的堆 也能求出一个通用的 求和公式:
sum = a1(a3+a2+2) + a2(a3+2)+ a3+2
当 有四个数的时候
a1 a2 a3 a4
sum = a1(a4+a3+a2+3) + a2(a4+a3+3) + a3(a4+2) + a4+3
不知道有没有发现什么规律~_ ~
sum_n = a1(an +…a2+n-1) + a2(an+an-1 +…+a3+n-1) + …+ an + n-1
用数学归纳法很好证的
也就是a1出现的次数最多 其次是 a2 。。。。 an 于是那么肯定就是
a1是最大的 其次是 a2 最后是 an
于是就可以做出来啦 =_+
#include <stdio.h>
#include <stdlib.h>
void input(int ,int[]);
int cmp(const void*,const void*);
long long q_zhi(int,int[]);
int main(void)
{
int n;
scanf("%d",&n);
int sz[n];
input(n,sz);
qsort(sz,n,sizeof(int),cmp);
printf("%lld",q_zhi(n,sz));
return 0;
}
int cmp(const void*a,const void*b)
{
return *(int*)b - *(int*)a;
}
long long q_zhi(int n,int sz[])
{
int i;
long long ans = 0;
for(i = 0;i < n-1;i++)
{
ans += (long long)(sz[i]+1)*(sz[i+1]+1);
sz[i+1] += sz[i];
}
return ans;
}
void input(int n,int sz[])
{
int i;
for(i = 0;i < n;i++)
{
scanf("%d",sz+i);
}
}