题解:Codeforces#499 Div.1

本文解析了Codeforces比赛#499 Div.1的五道题目,涵盖从简单到复杂的问题,如飞行器燃料优化、火箭故障检测、边界计算、火星探测器逻辑分析及三维空间长方体定位。提供了每题的算法思路与代码实现。

Codeforces#499 Div.1

其实总的来说,这次Div.1Div.1前四题挺水的,认真思考下都会做,代码量也不大,覆盖面广,难度适中,码量适中,解法自然,你可以利用这些题目,为自己的RatingRating上升提供一个强有力的援助。

A.Fly

题目大意

你有nn个点,初始重量为m(不包括燃料重),你需要从1号点开始依次走过所有点至nn号点,最后从n号点回到1好点,因此是从1号点上升,然后在2号点下降,再从2号点上升,在3号点下降…在n号点上升,在1号点下降,第ii个点有上升值a[i] 和降落值b[i]b[i],燃料减去(m+当前燃料重)÷÷ a[i]a[i](上升时,下降时为b[i]b[i]) ,求最小携带燃料重

数据范围

n1000n≤1000 , m1000m≤1000 , a[i],b[i]1000a[i],b[i]≤1000 , 最小携带燃料重 1e91e9

Sol

一开始想到二分,但发现可以不用带loglog

然后发现可以倒着做,假设最后一次回到1时燃料全用完就可以了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int _=1005;
inline int read()
{
    char ch='!';int z=1,num=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')z=-1,ch=getchar();
    while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
    return z*num;
}
int n,m,a[_],b[_];
double k;
int main()
{
    n=read();scanf("%lf",&m);
    for(int i=1;i<=n;++i)a[i]=read();
    for(int i=1;i<=n;++i)b[i]=read();b[n+1]=b[1];
    bool flag=0;
    for(int i=n;i;--i)
    {
        if(b[i+1]==1){flag=1;puts("-1");break;}
        k+=1.0*(m+k)/(b[i+1]-1);
        if(a[i]==1){flag=1;puts("-1");break;}
        k+=1.0*(m+k)/(a[i]-1);
    }
    if(!flag)printf("%.6lf\n",k);
    return 0;
}

B.Rocket

题目大意

有个数xx,可以进行询问一个值y,会返回一个“-1,0, 1”中的值,-1表示xyy小,0表示x刚好等于yy,此时你需要立刻结束程序,1表示xyy大。但是机器会出问题,可能会返回一个与原本值相反的值,例如-1返回1,1返回-1(但0仍然返回0)。你有不超过60次询问机会,请你打印出所有询问。

数据范围

n30 , m1e9m≤1e9

Sol

观察到n最大只有30,不就是不停询问1得到序列p,然后用230230 二分xx就好了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int _=35;
inline int read()
{
    char ch='!';int z=1,num=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')z=-1,ch=getchar();
    while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
    return z*num;
}
int m,n,a[_];
int main()
{
    m=read(),n=read();
    for(int i=1;i<=n;++i)
    {
        puts("1");fflush(stdout);
        a[i]=read();
        if(!a[i]){puts("1");exit(0);}
    }
    int l=2,r=m;int now=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;now++;
        if(now==n+1)now=1;
        printf("%d\n",mid);fflush(stdout);
        int x=read();
        if(!x){exit(0);}
        if((x==-1&&a[now]==-1)||(x==1&&a[now]==1))l=mid+1;
        else r=mid-1;
    }
    return 0;
}

C.Border

题目大意

你有n个数,每个数都可以使用无限次,你可以将某些数相加得到一个新数(也可以自己加自己),请记录这些数字(包括构造的新数)在mod k意义下有多少种

数据范围

n100000n≤100000 , k100000k≤100000 , a[i]1e9a[i]≤1e9 ,所有数字均已十进制给出

Sol

这个其实博主也不会理性证明,但是感性想想还是很好的。如果一个数XX在modK意义下的和其他数的GCD为dd,那么在K范围内的dd的倍数也一定成立(因为任意搭配,个数无限),然后统计就好啦

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int _=100005;
inline int read()
{
    char ch='!';int z=1,num=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')z=-1,ch=getchar();
    while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
    return z*num;
}
int n,k,a[_],p[_];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
    n=read(),k=read();
    for(int i=1;i<=n;++i)a[i]=read()%k;
    for(int i=1;i<=n;++i)a[i]=gcd(a[i],k);
    int d=0;
    for(int i=1;i<=n;++i)d=gcd(d,a[i]);
    for(int i=0;i<k;i+=d)p[++p[0]]=i;
    printf("%d\n",p[0]);
    for(int i=1;i<=p[0];++i)printf("%d ",p[i]);
    puts("");
    return 0;
}

D.Mars rover

题目大意

你有一棵树,树上的叶子节点权值由输入决定,除叶子节点外所有点具有一个运算操作,是(与,或,异或,取反)中一个,该节点值由其叶子节点进行该运算操作决定。

询问:对于所有叶子节点,若将该节点的值取反,是否会对根节点(1号点产生影响),是为1否为0。

数据范围

n1e6 , 叶节点值均 0,1∈0,1

Sol

预处理出树上各个节点的值,然后dp一下,f[i]f[i]表示将该节点取反后是否会影响到根节点的值。

那么f[u]f[u]显然受f[fa[u]]f[fa[u]]影响,只有在f[fa[u]]=1f[fa[u]]=1的情况下,f[u]f[u]才有可能能取到1,然后其实代码挺容易打的

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int _=1001000;
int n,c[_],s[_][2],f[_];
char op[20];
void Pre(int u)
{
    for(int i=0;i<2;++i)
    {
        int v=s[u][i];
        if(!v)continue;
        Pre(v);
    }
    if(c[u]==1)f[u]=f[s[u][0]]&f[s[u][1]];
    if(c[u]==2)f[u]=f[s[u][0]]|f[s[u][1]];
    if(c[u]==3)f[u]=f[s[u][0]]^f[s[u][1]];
    if(c[u]==4)f[u]=f[s[u][0]]^1;
}
bool dp[_];
void dfs(int u,int fa)
{
    if(dp[fa]&&fa)
    {
        int k=s[fa][0]==u?1:0,t=f[u]?0:1;
        if(c[fa]==1)dp[u]=f[s[fa][k]]&t,dp[u]^=f[fa];
        if(c[fa]==2)dp[u]=f[s[fa][k]]|t,dp[u]^=f[fa];
        if(c[fa]==3)dp[u]=f[s[fa][k]]^t,dp[u]^=f[fa];
        if(c[fa]==4)dp[u]=dp[fa];
    }
    for(int i=0;i<2;++i)
    {
        int v=s[u][i];
        if(!v)continue;
        dfs(v,u);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",op);
        if(op[0]=='I')scanf("%d",&f[i]);
        else
        {
            if(op[0]=='A')scanf("%d%d",&s[i][0],&s[i][1]),c[i]=1;
            if(op[0]=='O')scanf("%d%d",&s[i][0],&s[i][1]),c[i]=2;
            if(op[0]=='X')scanf("%d%d",&s[i][0],&s[i][1]),c[i]=3;
            if(op[0]=='N')scanf("%d",&s[i][0]),c[i]=4;
        }
    }
    dp[0]=dp[1]=1;Pre(1);dfs(1,0);
    for(int i=1;i<=n;++i)
    {
        if(c[i])continue;
        printf("%d",dp[i]?f[1]^1:f[1]);
    }puts("");
    return 0;
}

E.Store

题目大意

在一个三维空间中,存在一个长方体,但并不知道它的具体位置,但有nn个点在长方体内,m个点不在长方体内,先判断是否合法,若合法再给出k组询问,每次询问某个点是否在长方体内(回答在,不在,或不确定)

数据范围

XMax,YMAX,ZMAX,n,m,k1e5XMax,YMAX,ZMAX,n,m,k≤1e5

Sol

KD-Tree暂时不会,会了再回来更

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值