题意
我们可以将原题转化为这样一个较为形象的问题:
你可以任选 c i c_i ci 个数,使得它们的和为 s u m i sum_i sumi,求一种方案使得所选的数的平方和最小。
分析
我们用一些简单的初中数学知识进行推导:
设两个数 a , b ∈ ( 0 , + ∞ ) a,b\in(0,+∞) a,b∈(0,+∞)
∵ ( a + b ) 2 = a 2 + b 2 + 2 a b , a > 0 , b > 0 ∵(a+b)^2=a^2+b^2+2ab,a>0,b>0 ∵(a+b)2=a2+b2+2ab,a>0,b>0
∴ a 2 + b 2 < ( a + b ) 2 ∴a^2+b^2<(a+b)^2 ∴a2+b2<(a+b)2
由此,我们可以得到本题的基本思路:使每个选择的数都尽量小(因为把一个大数拆成两个小数显然更优),也就是取平均数。
然而,我们可以发现, s u m c \dfrac{sum}{c} csum 不一定是整数,这时我们可以这样做:将余数全部拆分为 1 1 1,加到其他的平均数里面。
举个例子,假设 s u m = 11 sum=11 sum=11, c = 3 c=3 c=3。
我们求出平均数为 3 3 3,余数为 2 2 2:
3 | 3 | 3 | ··· | 2 |
---|
我们将 2 2 2 分为两个 1 1 1,加到 3 3 3 里面:
3 | 4 | 4 |
---|
这就是最优解。
代码
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int c,sum;
int a,b,ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&c,&sum);
a=sum/c;//平均数
b=sum-a*c;//余数
ans=a*a*(c-b)+(a+1)*(a+1)*b;
printf("%d\n",ans);
}
return 0;
}