话不多说直接贴代码
void solve(){
int n, m;
while(cin >> n >> m){
double re = 0;
uu(i, 1, n){
double pos = (double)i / n * (n+m);
re += fabs(pos - floor(pos + 0.5)) / (n+m);
}
cout << re*1e4 << endl;
}
}
lrj书已经给出了一定深度的解释,但采集如我仍无法理解pos、re累加的由来,此文写给同样萌萌的你们。
- 设原周长 C C C
- 加入 m m m个点后周长为 n + m n+m n+m
- n + m n+m n+m个点每点坐标为 i i i
- 原来n个点每点坐标为 ( n + m ) / n ∗ i = ( 1 + m / n ) ∗ i (n+m)/n*i=(1+m/n)*i (n+m)/n∗i=(1+m/n)∗i
- 需要注意的是这里的3和4的 i i i不是一回事,3仅是说明加入 m m m个点后每个点的坐标都在整数位置上,4的 i i i说明原来的n个点不一定在整数位置上,仅当m是n的整数倍时 i [ 0 , . . . , n − 1 ] i[0,...,n-1] i[0,...,n−1]点在整数位。
综上可知为了加入
m
m
m个点后原来的
n
n
n个点需要各自跑到最近的整数位置上,这就是floor(pos+0.5)的由来,那么为什么后面会有
/
(
n
+
m
)
/(n+m)
/(n+m)呢,别急下面👇解释:
我们知道现在的点坐标是由
C
C
C缩放到
n
+
m
n+m
n+m的,那么回到原来的坐标就需要
i
/
(
n
+
m
)
∗
C
i/(n+m)*C
i/(n+m)∗C,这里的
i
i
i是加入
m
m
m个点后的整数坐标,
C
C
C是公因式可以提出来放在最后乘,因此每一步计算累加的时候只看见了
.
.
.
/
(
n
+
m
)
.../(n+m)
.../(n+m)而不见
C
C
C。(题中
C
=
1
e
4
C=1e4
C=1e4)