10月6日训练总结

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));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值