A题,分蛋糕,输入蛋糕个数,以及每一个的半径,以及宾客的人数,要求每个宾客得到的蛋糕体积一样,自己也要一块,问最大分到的是多少。
思路,对答案二分,检查是否可以成功分那么多快蛋糕。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#define p1 acos(-1.0)
using namespace std;
double a[10000+6];
int n,m;
bool solve(double q)
{
int t=0;
for(int i=1;i<=n;i++)
{
t=t+(int)(a[i]/q);
if(t>=m)
return true;
}
return false;
}
int main()
{
int i;
scanf("%d",&i);
while(i--)
{
scanf("%d%d",&n,&m);
m++;
double l=0,r=0;
int s,t;
for(s=1;s<=n;s++)
{
scanf("%lf",&a[s]);
a[s]=a[s]*a[s]*p1;
r=max(r,a[s]);
}
double mid;
while(r-l>0.00001)
{
mid=(r+l)/2.0;
if(solve(mid))
{
l=mid;
}
else
{
r=mid;
}
}
printf("%.4lf\n",l);
}
}
O题:
把n天的钱分成M个组来花,求分成的组的最大可花销数的最小值。
思路:
对答案二分,检查最后分成的组是否小于等于M即可。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
typedef long long ll;
ll a[100000];
ll answer;
ll n,m;
bool check(int x)
{
int c=1;
int ans=a[0];
if(ans>x)
{
return false;
}
for(int i=1;i<n;i++)
{
if(a[i]>x)
{
return false;
}
if(ans+a[i]<=x)
{
ans+=a[i];
}
else
{
c++;
ans=a[i];
}
}
if(c>m)
{
return false;
}
else
{
return true;
}
}
int main(void)
{
cin>>n>>m;
ll sum=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
sum+=a[i];
}
ll l=0,r=sum,mid;
while(r-l>1)
{
mid=(l+r)/2;
if(check(mid))
r=mid;
else
l=mid;
//cout<<1;
}
cout<<r<<endl;
}
B题:
一共n个城市m个邮箱,给定每个城市的人数,每个邮箱大小一样,每个城市至少一个邮箱,可以很多,请问如何邮箱可装选举信的数量最小。
思路,对邮箱大小进行二分,检查每个城市能否装下即可,代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
typedef long long ll;
ll a[1000000];
ll answer;
ll n,m;
bool check(int x)
{
ll ans=0;
for(int i=0;i<n;i++)
{
if(a[i]%x==0)
ans+=a[i]/x;
else
ans+=a[i]/x+1;
}
if(ans<=m)
return true;
return false;
}
int main(void)
{
while(cin>>n>>m)
{
if(n==-1)
break;
ll maxs=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
maxs=maxs>a[i]?maxs:a[i];
}
if(n==m)
{
cout<<maxs<<endl;
continue;
}
ll l=0,r=maxs,mid,ans;
while(l<r)
{
mid=(l+r)/2;
if(check(mid))
{
r=mid;
ans=mid;
}
else
l=mid+1;
}
cout<<ans<<endl;
}
}
C题:
没有前导零且每一位数都不一样的数是神奇数,请问小于X的神奇数有多少个?
思路:
因为要求多组输入,所以先预处理,然后二分查找即可代码如下:
#include<stdio.h>
#include<string.h>
int base[10000000];
int idx=0;
int init()
{
for(int i=1;i<10000000;i++)
{
int temp=i;
bool cas[20]={0};
while(temp)
{
if(cas[temp%10]==1)
break;
cas[temp%10]=1;
temp=temp/10;
}
if(temp==0)
{
base[idx++]=i;
}
}
}
int rfind(int x)
{
int l=0,r=idx-1;
while(l<=r)
{
int m=(l+r)/2;
if(base[m]<x)
l=m+1;
else
r=m-1;
}
return l;
}
int main()
{
init();
int n;
while(~scanf("%d",&n))
{
printf("%d\n",rfind(n));
}
}