题源:https://cometoj.com/contest/58/problem/B?problem_id=2757
题目描述
1267年,战争的味道在空气中弥漫,强大的尼弗迦德帝国蓄势待发。觊觎着雅鲁加河对岸的北方领域。莱里亚的女王米薇为了抵御尼弗迦德帝国的进攻,在莱里亚王国内建造了 nn 个城市。第 ii 个城市中居住着 w_iwi 个公民。当尼弗迦德帝国进攻某一个城市时,其他所有城市将支援被进攻的城市。但这些城市的居民会因为支援其他城市而产生不满意度。
当城市 aa 要前往城市 bb 支援时,会产生 (w_a-w_b)^2(wa−wb)2 点不满意度。
米薇女王想知道对于每个城市被进攻时,分别会产生多少点不满意度。
即对于每个城市 xx ,你需要回答 \sum_{i=1}^n{(w_i-w_x)^2}∑i=1n(wi−wx)2 的值。
输入描述
第 11 行一个整数 nn ,代表有 nn 座城市。
第 22 行 nn 个整数,第 ii 个整数 w_iwi 代表第 ii 个城市的人口数量。
- 2 \leq n \leq 10^52≤n≤105
- 1 \leq w_i \leq 10^61≤wi≤106。
输出描述
一行 nn 个整数,分别是第 11 个被攻击产生的不满意度到第 nn 个城市被攻击的不满意度。
样例输入 1
3 3 3 3
样例输出 1
0 0 0
样例输入 2
3 3 4 5
样例输出 2
5 2 5
样例输入 3
5 19 4326 7891 744 999
样例输出 3
82004658 55159127 173256882 64500983 59594018
题解:
解题思路:
朴素算法是双重循环按照题意求每一个结果(Wa-Wb)^2会超时。
仔细思考发现(Wa-Wb)^2=Wa^2+Wb^2-2*Wa*Wb,可以进行公式转换。于是这就能想法转成一个循环来做了。
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
int a[N];
int main()
{
// freopen("input.txt", "r", stdin);
//提交时注释,调试时取消注释!!!
int n;
cin>>n;
ll sum1=0;//统计所有城市公民之和
ll sum2=0;//统计所有城市公民a[i]^2之和
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum1+=a[i];
sum2+=a[i]*a[i];
}
for(int i=0;i<n;i++)
{
ll res=(n-1)*a[i]*a[i]+(sum2-a[i]*a[i])-2*a[i]*(sum1-a[i]);
printf("%lld ",res);
}
cout<<endl;
return 0;
}
提交的时候发现,我把a[N]的类型改成int就错了。原因是a[i]*a[i]爆int了。a[i]和a[i]相乘不会将int自动转换成long long类型。
自动类型转换只限于在表达式所具有的类型之内转换。