二分每块派的面积,用各圆面积的整除结果统计可切份数。
OJ: noi_openjudge
题目 ID: ch0111-05
难度:普及-
标签:二分几何python
日期: 2026-07-30 23:01
题意
把若干圆形派分给所有朋友和自己,每人得到一块面积相同的派,求这块派的最大面积。
思路
半径为 int(面积 / x) 块;所有派合计至少有 F + 1 块时,
代码
Python代码
python
from math import pi
pie_count, friend_count = map(int, input().split())
areas = [pi * radius * radius for radius in map(int, input().split())]
needed_pieces = friend_count + 1
def can_share(area: float) -> bool:
return sum(int(pie_area / area) for pie_area in areas) >= needed_pieces
low, high = 0.0, max(areas)
for _ in range(100):
middle = (low + high) / 2
if can_share(middle):
low = middle
else:
high = middle
print(f"{low:.3f}")C++代码
cpp
/*
* 这个题目最坑的是 pi 要定义成 3.141592653589
* */
#include <cstdio>
#define pi 3.141592653589
#define JD 0.00001
typedef long long ll;
ll n,f;
double m[10005];
double _max=0;
void init(){
scanf("%lld%lld",&n,&f);
f++;
int i;
double t;
for (i=1;i<=n;i++){
scanf("%lf",&t);
m[i] = pi*t*t;
if( _max < m[i]) _max = m[i];
}
}
ll check(double num){
ll i,cnt = 0;
for (i=1;i<=n;i++){
cnt += (m[i] / num);
}
return cnt;
}
double first_g(double l,double r){
double m;
while( l + JD < r ) //表示l和r没有重合
{
m = (l+r)/2; // 取中间位置
ll cnt = check(m);
if(cnt >= f) //表示 [m+1,r) 满足条件
l = m+JD;
else
r = m;
}
return l;
}
int main(){
init();
int i,cnt = 0;
double ans = first_g(0,_max);
printf("%.3lf\n",ans-JD);
return 0;
}复杂度
二分固定 100 次,时间复杂度为
总结
实数二分不必等到端点相等,迭代足够多次即可保证输出精度。