ACM-BestCoder Round #22

A-NPY and FFT

题意:
给一个十进制数,然后将它转化为二进制数,然后对该二进制数翻转,相当于从后面看过来,最后将新的二进制转换回十进制即可。
分析:
就是普通、简单的进制转换,详见代码。
源代码:
#include <cstdio>

int main()
{
    int cas;
    char bina[100];
    scanf("%d", &cas);
    while(cas--)
    {
        int data, len=0;
        scanf("%d", &data);
        while(data)    // 十进制转二进制
        {
            bina[len++] = data%2;
            data /= 2;
        }
        int tmp=1, ans=0;
        --len;
        while(len>=0)  // 反向的二进制转十进制
        {
            ans += bina[len--]*tmp;
            tmp *= 2;
        }
        printf("%d\n", ans);
    }
    return 0;
}


B-NPY and arithmetic progression

题意:
给出4个数a1,a2,a3,a4,分别代表数字1,2,3,4的数量,问能否在使用每一个数字且仅使用1次的情况下,将给出的数据分成一些元素个数不小于3的部分,且每部分中的元素构成等差数列。
分析:
首先考虑1,2,3,4构成等差数列的情况,在元素个数不小于3的条件下,无非如下这么多种情况:(全1),(全2),(全3),(全4),(1,2,3,4),(1,2,3),(2,3,4)。既然只有这些情况满足条件,那么就可以一步一步枚举下去,搜索所有可能出现的情况。如果最终所有的数字被分配成了前面的那些情况,说明存在解法,反之如果数字的数量用完但是没有出现符合条件的情况,那么则不存在解法。所以关键就看最终剩下什么样的状态,可以想象每一次分配前面那几种情况后,最终剩下符合条件的情况只有空集,或者3个以上相同数字的集合,如果出现其它情况,则可判定无解。
源代码:
#include <cstdio>

int dfs(int a1, int a2, int a3, int a4)
{
    // 全一样的成员,或无影响的空成员即满足条件
    if((a1>=3||a1==0) && (a2>=3||a2==0) && (a3>=3||a3==0) && (a4>=3||a4==0))
    {
        return 1;
    }
    // 组合(1,2,3,4),如果不先搜索这组可能会暴栈
    if(a1>0 && a2>0 && a3>0 && a4>0)
    {
        if(dfs(a1-1, a2-1, a3-1, a4-1))
        {
            return 1;
        }
    }
    // 组合(1,2,3)
    if(a1>0 && a2>0 && a3>0)
    {
        if(dfs(a1-1, a2-1, a3-1, a4))
        {
            return 1;
        }
    }
    // 组合(2,3,4)
    if(a2>0 && a3>0 && a4>0)
    {
        if(dfs(a1, a2-1, a3-1, a4-1))
        {
            return 1;
        }
    }
    return 0;
}

int main()
{
    int cas, a1, a2, a3, a4;
    scanf("%d", &cas);
    while(cas--)
    {
        scanf("%d%d%d%d",
              &a1, &a2, &a3, &a4);
        if(dfs(a1,a2,a3,a4))
        {
            puts("Yes");
        }
        else
        {
            puts("No");
        }
    }
    return 0;
}

C-NPY and shot

题意:
从高h的地方,以初速度v抛物体,问在最好的仰角下物体能被抛出多远。
分析:
可以考虑从0角度开始抛物体,直到90度,很明显抛出的距离是先增后减的,也就是说抛出角度与抛出距离是成凸函数关系的,找凸函数的最大值常用的方法是三分查找,原理见另一篇文章,传送门( 点击打开链接),其实实现起来也和二分查找很类似。这样之后,就可以确定最佳的抛射角度了,剩下的就是物理问题了,其物理过程如下图:

要解这个物理模型,需要知道这么几个物理公式:
1、加速度公式
a = (vt-v0) / t
2、恒加速度下的路程公式
s = v0*t + (a*t^2)/2
有了上面的公式,就可以求解最远抛出距离问题了,最后还需要的一点知识就是速度的分解,这里按竖直和水平两个方向进行分解,然后就是利用公式及其变形来算时间、路程最终求解出答案了。
源代码:
#include <cstdio>
#include <cmath>

#define g 9.8

double v, h;

double solve(double angle)
{
    // 上升到最高点所用时间(沿竖直方向计算)
    double t1 = v*sin(angle) / g;
    // 上升到最高点所上升的高度(沿竖直方向计算)
    double h1 = v*sin(angle)*t1 - g*t1*t1/2;
    // 从最高点下落到地面的时间(沿竖直方向计算)
    double t2 = sqrt(2*(h1+h)/g);
    // 最远抛出的距离(沿水平方向计算)
    return v*cos(angle) * (t1+t2);
}

double trisection_search(double left, double right)
{
    // 三分角度,找到最优解(求函数最大值下的自变量值)
    double midl, midr;
    while (right-left > 1e-7)
    {
        midl = (left + right) / 2;
        midr = (midl + right) / 2;
        if(solve(midl) >= solve(midr)) right = midr;
        else left = midl;
    }
    return left;
}

int main()
{
    int cas;
    scanf("%d", &cas);
    while(cas--)
    {
        scanf("%lf%lf", &h, &v);
        double ans = trisection_search(0, 90);
        printf("%.2f\n", solve(ans));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值