Graveyard
题面翻译
题目描述
在一个周长为 10000 10000 10000的圆上等距分别着 n n n个雕塑。现在又有 m m m个新雕塑加入(位置可以随意),希望所有 n + m n+m n+m个雕塑在圆周上分布均匀。这就需要移动其中一些原有的雕塑。要求 n n n个雕塑移动的总距离尽量小。
输入格式
输入包含若干组数据。每组数据仅一行,包含两个整数 n , m ( 2 < = n < = 1000 , 1 < = m < = 1000 ) n,m(2<=n<=1000,1<=m<=1000) n,m(2<=n<=1000,1<=m<=1000),即原始雕塑的数量和新加的雕塑的数量。输入结束标志为文件结束符( E O F EOF EOF).
输出格式
对于每组数据,输出仅一行,为最小总距离,精确到 1 0 − 4 10^{-4} 10−4
Translated by @洛谷万岁
又是一个数学问题。
我们把这个圆环当成一个从头尾相接的轴,这里先把整个圆环的周长设为
1
1
1,那么当前的点在圆环上的位置就为:
0
n
,
1
n
,
2
n
,
3
n
,
…
,
n
−
1
n
\frac{0}{n} , \frac{1}{n} , \frac{2}{n} , \frac{3}{n},\dots , \frac{n-1}{n}
n0,n1,n2,n3,…,nn−1,即我们让第一个点当成了原点,之后的点在
x
x
x 轴上递增。
这时候如果我们要再加入 m m m 个雕像,那么最后应该形成的局面应该是 0 n + m , 1 n + m , … , n + m − 1 n + m \frac{0}{n+m} , \frac{1}{n+m} , \dots , \frac{n+m-1}{n+m} n+m0,n+m1,…,n+mn+m−1 ,这时候加入了 m m m 个雕像第一个点仍然可以作为原点,就如样例一一样,我们可以让拍完之后的应该填入的环先找一个环放到原点头上。
我们让所有点都乘以 n + m n+m n+m,就相当于让整个圆的周长变为了 n + m n+m n+m,那么之前的点就变为了:
0 n , 1 ∗ ( n + m ) n , 2 ∗ ( n + m ) n , … , ( n − 1 ) ∗ ( n + m ) n \frac{0}{n} , \frac{1*(n+m)}{n} , \frac{2*(n+m)}{n} , \dots , \frac{(n-1)*(n+m)}{n } n0,n1∗(n+m),n2∗(n+m),…,n(n−1)∗(n+m)
之后的点变为了:
0 , 1 , 2 , … , n + m − 1 0 , 1 , 2 , \dots , n+m-1 0,1,2,…,n+m−1
这时候我们想要移动到的位置全部变为了整数,如果对于一个小数要移动到一个离他最近的整数,就只需要四舍五入取整即可,如果对于一个整数,那他就不用移动了。
代码:注:round()
函数是取整函数。
#include<iostream>
#include<cmath>
#pragma warning (disable : 4996)
using namespace std;
const int N = 1010;
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
double res = 0;
for (int i = 1; i < a; i++) {
double t = 1.0 * i * (a + b) / a;//取加入之前的点
res += abs(t - round(t)) / (a + b);
}
printf("%.4lf\n",res*1e4);
}
return 0;
}