解题报告3

【题目大意】
是时候回忆一下旧数学的灾难性时刻了。是的,猴子爬在涂了油的竹子上的数学小问题。就像这样:“一只猴子正试图爬到涂了油的竹子的顶端。当他爬上3英尺时,他滑下2英尺。爬上3英尺需要3秒钟。滑下2英尺需要1秒。如果杆子有12英尺高,猴子需要多长时间才能到达顶端?”当我被问到这个问题时,我很认真。但过了一会儿,我想杀了猴子,而不是做可怕的数学!我有不同的计划给竹子上油的人。现在,我们这些问题解决者,也得到了类似的涂油竹子。所以,我们认为我们可以做得比传统的猴子更好。所以,我先尝试了。我跳了起来,爬了3.5英尺(比猴子好!哈!)但就在那一秒钟,我滑倒在地。在那之后,我什么都记不起来了,当我醒来时,我发现自己躺在床上,周围那些问题解决者焦虑的脸。所以,像以前一样,猴子用涂了油的竹子赢了。所以,我做了另一个计划(不知何故我想打败猴子),我用梯子代替竹子。起初我在地面上。在每次跳跃中,我只能从当前的横档(或地面)跳到下一个横档(不能跳过横档)。最初我设置了我的力量系数k。k的意思是,在任何一次跳跃中,我不能跳超过k英尺。如果我在一次跳跃中正好跳了k英尺,k减1。但如果我跳不到k英尺,k保持不变。例如,让横档离地面的高度分别为1、6、7、11、13,k为5。
现在的步骤是:
1.从地面跳1英尺到第一级(地面到1)。因为我跳了不到k英尺,k仍然是5英尺。
2.跳了5英尺的下一个横档(1至6)。所以,k变成4。
3.第三级跳1英尺(6到7)。所以,k仍然是4。
4.跳了4英尺的第四级(7至11)。这个k变成3。
5.跳了2英尺的第五级(11至13)。所以k仍然是3。
现在给你梯子的横档离地面的高度,你必须找到最小的强度系数k,这样我才能到达最上面的横档。
【输入】
输入以整数T(≤500)开始,表示测试用例的数量。每种情况都从一行开始,其中包含一个整数n,表示阶梯中的横档数。下一行包含n个空格分隔的整数,r1,r2……rn(1≤r1<r2<……<rn≤107)表示横档离地面的高度。所有情况下,1≤n≤10,10<n≤105的情况除外。
【输出】
对于每个案例,打印案例编号和k的最小值,如上所述。
例如:

【解题思路】
这题题干闲话比较多,对于我这种英语zz来说就是地狱。我们直接来看题干比较重要的部分。通过题意可以了解到k要大于两横档之间的最大差值,并且两横档之间的差值达到k,k就要减一。对于k值的寻找就要用到省时的二分法了。定义左端为1,右端开大一些,先取一个中间值,将这个中间值作为k的值。与每两个横档之间的差值进行比较(这里要注意地面到第一个横档的距离也要考虑进去),如果遇到相等的情况,k就减一,一旦遇到差值大于k的情况就跳出循环,并令区间左端大于看,再重新进行。如果k满足情况(这里忘了说,要定义一个缓存将满足条件的k进行保存),就使区间的右端小于k,判断k是否是最小的值。如此下去,k的最小值就可以确定。
大致的框架如下:

将横档存入一个数组a[ ],并使数组的第一个值为0,用来表示地面;
for(int i = 1; i <= n; i++)
    {
        int m = a[i] - a[i-1];
        if(x == m) //遇到相同值,k要减一
        {
            x--;
        }
        else if(x < m) //不满足条件返回0
        {
            return 0;
        }
    }
return 1;
二分法用来寻找k值:
int l=1,r=100000000;
        while(l <= r)
        {
            int mid = (l+r) / 2;
            int m = du(mid);
            if(m == 1)
            {
                r = mid-1;
                cnt = mid; //缓存上一个满足条件的k
            }
            else
            {
                l = mid + 1;
            }
        }

【参考代码】

#include<bits/stdc++.h>
using namespace std;
int n;
int a[1000000];
int du(int x)
{
    for(int i = 1; i <= n; i++)
    {
        int m = a[i] - a[i-1];
        if(x == m)
        {
            x--;
        }
        else if(x < m)
        {
            return 0;
        }
    }
    return 1;
}
int main()
{
    int t;
    cin >> t;
    int s = t;
    while(t--)
    {
        scanf("%d",&n);
        a[0]=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }
        int cnt = 0;
        int l=1,r=100000000;
        while(l <= r)
        {
            int mid = (l+r) / 2;
            int m = du(mid);
            if(m == 1)
            {
                r = mid-1;
                cnt = mid;
            }
            else
            {
                l = mid + 1;
            }
        }

        printf("Case %d: %d\n",s - t,cnt);

    }
    return 0;
}

【题目大意】
求解方程:p∗e^(−x) + q∗sin(x) + r∗cos(x) + s∗tan(x) + t∗x^2 + u = 0。其中0≤x≤1。
【输入】
输入由多个测试用例组成,并由一个EOF终止。每个测试用例由6个整数组成:p、q、r、s、t和u(其中0≤p、r≤20和−20≤q、s、t≤0)。输入文件中最多有2100行。
【输出】
对于每一组输入,应该有一行包含x的值,最多可更正4位小数,
或字符串“No solution”,以适用者为准。
【解题思路】
该题与例题1差不多,不同的是该题多了系数的变量。由题意可得,该函数再0到1的区间内使单调递减的,所以,要想方程有解,0处的值必须大于等于零,1处的值必须小于等于0,这就是“No solution”这一条件的成立条件。同样,当二分的中值大于等于零时,中值应赋值给左端,小于零时应赋值给右端。
大致的框架如下:

mid = left + (right - left) / 2;
            if(F(mid) >= 0)
            {
                left = mid;
            }
            else
            {
                right = mid;

【参考代码】

#include <bits/stdc++.h>
#define F(x) (p*exp(-x) + q*sin(x) + r*cos(x) + s*tan(x) + t*x*x + u)
using namespace std;
void BS(int p,int q,int r,int s,int t,int u )
{
    double f0 = F(0);
    double f1 = F(1);
    if(f0  < 0 || f1 > 0  )
    {
        printf("No solution\n");
    }
    else
    {
        double mid,left = 0,right = 1;
        for(int i = 0; i < 100; i++)
        {
            mid = left + (right - left) / 2;
            if(F(mid) >= 0)
            {
                left = mid;
            }
            else
            {
                right = mid;
            }
        }
        printf("%.4lf\n",left);
    }

}
int main()
{
    int p,q,r,s,t,u;
    while(scanf("%d%d%d%d%d%d",&p,&q,&r,&s,&t,&u) != EOF)
    {
        BS(p,q,r,s,t,u);
    }
    return 0;
}

【题目大意】
给出若干个整数,询问其中是否有一对数的和等于给定的数。
【输入】
共三行:
第一行是整数n(0 < n <= 100,000),表示有n个整数。
第二行是n个整数。整数的范围是在0到10^8之间。
第三行是一个整数m(0 <= m <= 2^30),表示需要得到的和。
【输出】
若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行No。
例如:
输入	结果
4
2 5 1 4
6
1 5

【解题思路】
该题还是得用省时的二分法。将输入的数据先存在一个数组里并将数组从小到大进行排序。将输入的需要得到的和减去数组里的数就是我们需要在数组里找的数(s),如果找不到就输出“No”。因为我们事先已经将数组从小到大排列了,所以第一个符合条件的也一定是我们要找的答案(若有多个数对满足条件,选择数对中较小的数更小的)。在数组里寻找与s相等的数的过程就需要用到二分法。
大致的框架如下:

while(l - r<= 0)
    {
        int mid = (l + r) / 2;
        if(nums[mid] == s)
        {
            return true;
        }
        else if(nums[mid] < s)
        {
            l = mid + 1;
        }
        else
        {
            r = mid - 1;
        }
    }
    return false;

【参考代码】

#include<bits/stdc++.h>
using namespace std;
int nums[100010];
int n;
long long m;
int l;
int r;
int j;
bool finding(long long s)
{
    while(l - r<= 0)
    {
        int mid = (l + r) / 2;
        if(nums[mid] == s)
        {
            return true;
        }
        else if(nums[mid] < s)
        {
            l = mid + 1;
        }
        else
        {
            r = mid - 1;
        }
    }
    return false;
}
int main()
{
    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> nums[i];
    }
    cin >> m;
    sort(nums,nums + n);
    for(j = 0; j < n; j++)
    {
        long long s = m - nums[j];
        l = j + 1;
        r = n - 1;
        if(finding(s))
        {
            cout << nums[j] << " "<< s << endl;
            break;
        }
    }
    if(j == n)
    {
        cout<<"No"<<endl;
    }
    return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大摆钟快递

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

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

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

打赏作者

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

抵扣说明:

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

余额充值