政史特长生友谊赛Round3题解

Problem A、锑集合
给读入的每一个 Ai 打上标记,然后判断任意 Ai+Aj 有没有被打上标记即可。

#include<cstdio>
#include<cstring>
int t,n,a[2000];
bool f[80000];
bool &at(int n){return f[n+30000];}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",a+i);
        memset(f,0,sizeof f);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)at(a[i]+a[j])=true;
        bool ok=true;
        for(int i=1;i<=n;i++)
            if(at(a[i]))ok=false;
        printf("%d\n",int(ok));
    }
    return 0;
}

Problem B、洪水
一道锻炼思维
的好题,有多种方法。
第一个解法:把所有格子按海拔顺序排序,把每一档海拔与下一档之间能够容纳的水依次累加直到大于水的总体积。
第二个解法:把所有格子按海拔顺序排序,逐个计算含水海拔,第n个格子的含水海拔=(总水量+n个格子相对于0海拔的体积)÷n个格子的面积和,顺序读入后面格子海拔,如果此格高于已算出的含水海拔则终止。

#include<cstdio>
#include<algorithm>
using namespace std;
int h[300000],n,m,cas=0;
double v,H,k;
int main()
{
    scanf("%d%d",&n,&m);
    n*=m;
    for(int i=0;i<n;i++)scanf("%d",h+i);
    h[n++]=2147483647;
    sort(h,h+n);
    scanf("%lf",&v);v/=100.0;
    for(int i=1;i<=n;i++)
    {
        v+=h[i-1];H=v/i;
        if(H<h[i]){k=i;break;}
    }
    printf("%.2f %.2f%%\n",H,100.0*k/(n-1));
    return 0;
}

Problem C、最大公约数
我们先写个暴力程序搞出一些满足gcd(a,b)=a xor b=c的三元组(a,b,c),然后可以发现一个惊人的结论:c=a-b!
证明:不难发现a-b≤a xor b,且a-b≥c。假设存在c使得a-b>c,则c < a-b≤a xor b,与c=a xor b矛盾。
于是我们得出算法:枚举a和c,计算b=a-c,则gcd(a,b)=gcd(a,a-c)=c,所以只要验证是否存在c=a xor b即可,时间复杂度O(n log n)。

#include<cstdio>
int cnt[30000001],s[30000001],t,n;
int main()
{
    for(int i=1;i<30000001;i++)
        for(int j=i+i;j<30000001;j+=i)
            if((j^(j-i))==i)cnt[j]++;
    for(int i=1;i<30000001;i++)s[i]=s[i-1]+cnt[i];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        printf("%d\n",s[n]);
    }
    return 0;
}

Problem D、书架
不难想到用高度最小的书来填充第3层。
设f[i][j]表示第1、2层宽度分别为i、j时的最小总高度,
i=0:f[i+a[z].w][j]=min(f[i+a[z].w][j],f[i][j]+a[z].h)
i<>0:f[i+a[z].w][j]=min(f[i+a[z].w][j],f[i][j])
j=0:f[i][j+a[z].w]=min(f[i][j+a[z].w],f[i][j]+a[z].h)
j<>0:f[i][j+a[z].w]=min(f[i][j+a[z].w],f[i][j])
{z=1..n-1}
计算出f[][]然后就可以得出答案了。

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int f[3100][3100]; 
struct sh
{
    int h,w;
}a[150];
bool cmp(sh a,sh b)
{
    return a.h>b.h;
}
int main()
{
    int n,i,j,z,t,w=0,s=0;
    cin>>n;
    for(i=0;i<n;i++) { cin>>a[i].h>>a[i].w;s+=a[i].w;}
    sort(a,a+n,cmp);
    memset(f,INF,sizeof(f));
    f[0][0]=0;
    for(z=1;z<n;z++)
    for(i=s;i>=0;i--)
    for(j=s;j>=0;j--)
    if(f[i][j]!=INF)
    {
    if(i==0)
    f[i+a[z].w][j]=min(f[i+a[z].w][j],f[i][j]+a[z].h);
    else
    f[i+a[z].w][j]=min(f[i+a[z].w][j],f[i][j]);
    if(j==0)
    f[i][j+a[z].w]=min(f[i][j+a[z].w],f[i][j]+a[z].h);
    else
    f[i][j+a[z].w]=min(f[i][j+a[z].w],f[i][j]);
    }
    t=INF;
    for(i=1;i<=s;i++)
    for(j=1;j<=s;j++)
     if(f[i][j]!=INF)
     {
     w=max(i,j);
     w=max(w,s-i-j);
     t=min(t,(f[i][j]+a[0].h)*w);
     }
     cout<<t;
     return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值