【Acwing蓝桥杯笔记】四平方和&分巧克力

四平方和

image-20220403151551998

首先考虑时间复杂度 每一个数的范围都在0~2200之间

最多只能枚举两个数,考虑用空间换时间。

image-20220403160132154

image-20220403160148446

先试着用最基础的三重循环:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

const int N=2500010;

int n;

int main()
{
    cin>>n;
    for(int a=0;a*a<=n;a++)
      for(int b=a;a*a+b*b<=n;b++)
        for(int c=b;a*a+b*b+c*c<=n;c++)
        {
            int t=n-a*a-b*b-c*c;
            int d=sqrt(t);
            if (d*d==t)
            {
                printf("%d %d %d %d\n",a,b,c,d);
                return 0;
            }
        }
}

虽然是可行的,但是超时了。

所以开始采用二分:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

const int N=2500010;

struct Sum
{
    int s,c,d;
    bool operator<(const Sum &t)const
    {
        if(s!=t.s) return s<t.s;
        if(c!=t.c) return c<t.c;
        return d<t.d;
    }
}sum[N];

int n,m;

int main()
{
  cin>>n;
  //按照字典序枚举c、d组合
  for(int c=0;c*c<=n;c++)
    for(int d=c;c*c+d*d<=n;d++)
      sum[m++]={c*c+d*d,c,d};
      
      sort(sum,sum+m);
    for(int a=0;a*a<=n;a++)
      for(int b=0;a*a+b*b<=n;b++)
      {
          int t=n-a*a-b*b; //差值
          int l=0,r=m-1;
          while(l<r)
          {
              int mid =l+r>>1;
              if(sum[mid].s>=t) r=mid;
              else l=mid+1;
          }
          if(sum[l].s==t)
          {
             printf("%d %d %d %d\n",a,b,sum[l].c,sum[l].d);
             return 0;
          }
      }
      return 0;
}


哈希表做法(暂时不会):


分巧克力

image-20220403194606713

对于每一块巧克力来说,它能切出来的块数是随着边长的增大而递减的,边长越大,块数越小。

找到一个满足块数大于等于K的最大的一个点

if (f(mid)≥k) L=mid;else R=mid-1;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=100010;

int n,k;
int h[N],w[N];

bool check(int mid)
{
    int res=0;//最多能分多少块
    for(int i=0;i<n;i++)
    {
        res=res+(h[i]/mid)*(w[i]/mid);
        if(res>=k) return true;
    }
    return false;
}

int main()
{
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)  scanf("%d%d",&h[i],&w[i]);//读取每一块巧克力初始长度
    
    int l=1;//每一个小朋友至少获得一块1x1的巧克力,所以最小为1
    int r=1e5;
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",r);
    return 0;
}
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AKA山风点火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值