二分浮点数模板:
const double eps = 1e-7;
double l, r;
while(1+eps< r)
{
double mid=(l+r)/2;
if(ok(mid)) l=mid;
else r=mid;
}
然后两道模板题
HRBUST - 1530
题意:有一个很多个pi,每个pi都是一个圆,然后给你半径,问你能不能平均分给f+1个人,每个人拿到的pi必须是在同一个pi上的。
开始还以为也要分为圆呢,然后不用。。。。所以这道题,直接二分面积就好。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define eps 1e-4
#define pi acos(-1)
int a[10005];
int n,f;
int ok(double mid)
{
int ans=0;
for(int i=0;i<n;i++)
{
ans+=(a[i]/mid);
}
if(ans>=f+1) return 1;//注意要写= ,不写的话,就相当于到下面那步了,然后范围就会变小,如果mid=8时,ans==f+1,然后mid=6的时候ans=f+1,然后如果更新r的话,然后范围就小啦
else return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
scanf("%d %d",&n,&f);
int MAX=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]=a[i]*a[i];
if(a[i]>MAX) MAX = a[i];
}
double l=0,r=MAX;
while(l+eps<r)
{
double mid = (l+r)/2.0;
if(ok(mid)) l=mid;
else r=mid;
}
// cout<<r<<endl;
printf("%.4f\n",r*pi);//这个四舍五入什么的有或没有都没有关系,因为在误差范围内
}
return 0;
}
HDU - 4282
题意: X^Z + Y^Z + XYZ = K ,给你一个k问你满足这个表达式的x,y,z有几组。
K (0 < K < 2^31) X < Y, Z > 1
所以 z的范围是【2,31)
x的范围在【1,2^15)
y的范围在【2,2^15)
如果直接枚举的话一定超时,所以我们用把3重循环降为二重循环,枚举x,z,二分找y
然后注意限制条件,要不然会超时
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define inf 2148473647//如果2147483648超了int 的范围
long long M[40000][40];
void db()
{
for(int i=1;i<40000;i++)
{
M[i][1]=i;
for(int j=2;j<=31;j++) {if(M[i][j-1]*i<2147483648) M[i][j]=M[i][j-1]*i;}//
}
}
int ok(int x,int z,int cnt)
{
int l=x+1,r=40000;
while(r>=l)
{
int mid=(l+r)/2;
if(M[mid][z]==0) {r=mid;}//zheli
else if(M[mid][z]+(long long)x*mid*z>=cnt) r=mid;
else if(M[mid][z]+(long long)x*mid*z==cnt) return 1;//
else l=mid+1;
}
return 0;
}
int main()
{
long long k;
db();
while(scanf("%I64d",&k)!=EOF&&k)
{
int ans=0;
for(int x=1;x<40000&&x<k;x++)
{
for(int z=2;z<31;z++)
{
if(M[x][z]>=k) break;//
if(M[x][z]==0) break;//
long long cnt=k-M[x][z];
if(cnt-(long long)2*x*z<=0) break;
if(ok(x,z,cnt)) ans++;
}
}
printf("%d\n",ans);
}
return 0;
}