NEUQ2020-实验班-训练001-(6-10题)

NEUQ2020-实验班-训练001-(6-10题)

7-6 房间

题目

终于到了假期了,老师决定带领ACM队员们出去游山玩水,计划出行两天,这样的话中间就需要找个地方住宿一晚。

恰巧,老师带领队员们来到了这么一所酒店,这所酒店只有双人间(最多住两人)和三人间(最多住三人),但是价格不同,现在我们算上老师,一共有 n 个人,酒店的双人间价格是 a 元,三人间价格是 b 元,现在老师想知道怎样安排房间才能使得花销最小,你能帮助老师计算出最小的花销吗?

输入格式:

第一行给出一个正整数 T(1≤T≤1000),代表测试数据的组数。

接下来 T 行每行给出三个正整数 n,a,b,1≤n,a,b≤10​^9,含义如题。

输出格式:
输出包含 T 行,每行对应一组样例的输出。

输入样例:
2
2 20 200
3 20 20
输出样例:
20
20
思路:这个题真的是把我难的透透的了,当时人都傻掉了,刚开始看题,就以为是一道普普通通的线性规划题,但是,却怎么也过不了,直到有大佬给了我一些提醒:

  1. 当n<=2时,你需要选择a,b两个值中最小的那个房间。
  2. 当n>2时,就需要讨论房间单价问题了,也就是说,比较每个人身上所分担的房费,即:比较a/2与b/3的大小,
  3. 同时要注意,在两人间单价比较便宜时,应以两人间为主,所以,当n为偶数时,即可全分完,但一旦n为奇数,这时就会多出一个人,这时就要比较让这个人单独住一个两人间便宜,还是让他与另外两个人合并,同住一间三人间便宜。
  4. 在三人间比较便宜时,应该以三人间为主,但这时有三种情况去讨论,一个是,当n可以被3整除时,直接全买三人间,当n除以3余1时,就需要比较,住一个双人间,住一个三人间,或者让三个人与他合并住两个双人间,这三种情况哪个更加便宜。当n除以3余2时,只需要考虑住一个双人间,住一个三人间,哪个更便宜即可!

AC代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n;
        cin>>n;
        ll a,b;
        cin>>a>>b;
        if(3*a>2*b)
        {
            if(n%3==0)
            {
                cout<<n/3*b<<"\n";
            }
            else
            {
                if(n<3)
                {
                    cout<<min(a,b)<<"\n";
                }
                else
                {
                    if(n%3==1)
                    {
                        cout<<min((n/3-1)*b+2*a,min(n/3*b+a,n/3*b+b))<<"\n";
                    }
                    else
                    {
                        cout<<min((n/3-1)*b+3*a,min(n/3*b+a,n/3*b+b))<<"\n";
                    }
                }
            }
        }
        else{
            if(n%2==0)
            {
                cout<<n/2*a<<"\n";
            }
            else
            {
                if(n==1)
                {
                    cout<<min(a,b)<<"\n";
                }
                else
                {
                    cout<<min(n/2*a+b,min((n/2+1)*a,(n/2-1)*a+b))<<"\n";
                }
            }
        }
    }
    return 0;
}

7-7 二分查找

题目:

请实现有重复数字的有序数组的二分查找。

输出在数组中第一个大于等于查找值的位置,如果数组中不存在这样的数,则输出数组长度加一。

输入格式:
输入第一行有两个数,第一个数为数组长度n(≤10^6),第二个数为需要查找的数。

接下来有n个整数,以空格或换行符分隔。

输出格式:
输出待查找的数的位置。

输入样例:
5 4
1 2 4 4 5
输出样例:
3
样例解释:
有5个数,查找4出现的位置,4第一次出现在第3个位置,所以输出3。

思路:
这个题个人认为用二分查找就有些难以理解,或者有点麻烦,因为它是让我们找大于等于m的数,而不是m,所以说,m可能找不到,再用二分去找,就比较麻烦了,所以不如直接来个顺序查找,简单明了
需要注意的是,该题用顺序查找,再用cin输入的话会超时,所以应改为:scanf和printf,这样这个题就AC了!

AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[1000005];
int main()
{
    int  n;
    scanf("%d",&n);
	int x;
    scanf("%d",&x);
    bool flag = 0;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]>=x)
        {
            flag = 1;
            cout<<i+1<<endl;
            break;
        }
    }
    if(flag == 0)
    cout<<n+1<<endl;
    return 0;
} 

7-8 最长上升子序列

题目:
给定一个序列,求它的一个递增子序列,使它的元素个数尽量多,求该序列的最长上升子序列中元素个数。例如序列1,6,2,5,4,7的最长上升子序列是1,2,5,7或1,2,4,7,则其最长上升子序列中的元素个数为4。

输入格式:
第一行中输入序列的个数(不超过100),第二行中输入每个元素,以空格隔开。

输出格式:
输出该序列中最长上升子序列中的元素个数。

输入样例:
在这里给出一组输入。例如:
6
1 6 2 5 4 7
输出样例:
在这里给出相应的输出。例如:
4
思路:
该题是个模板题,如果有的童鞋不理解最长上升子序列,下面这篇文章大家可以看一下:
最长上升子序列(模板)

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a[105];int dp[105];
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        dp[i] = a[i];
    }
    int l = 1;
    for(int i=1;i<n;i++)
    {
        if(dp[i-1]>a[i])
        {
            dp[i-1] = a[i];
        }
        else
        {
            dp[i]=a[i];
            l++;
        }
    }
    cout<<l;
    return 0;
}

7-9 求区间和

题目:

本题会给你一段长度为N的整数序列,并进行K次询问。每次询问要求你给出区间a到b的和(序列下标由1到N)。由于区间和可能较大,请你输出它对10000019取模的结果。(注意:如果你想不到高效的做法,可以用朴素算法得到一部分分,但本题满分需要你用一个比较高效的做法。)

输入格式:
首先一行整数N,代表序列长度。
接下来一行N个整数,为序列内容。
接下来一行整数K,代表对区间和的询问次数。
接下来K行,每行两个整数a和b,请你输入序列的第a到b号元素(含)的和取模后的结果。

输出格式:
一共K行,每行一个整数,代表询问的区间和取模后的结果。

输入样例:
在这里给出一组输入。例如:
5
1 2 3 4 5
3
1 5
2 3
3 3
输出样例:
在这里给出相应的输出。例如:
15
5
3
数据限制:
N<=10^6
K<=10^​5
思路:
一般思路,一般去做,但是得不全分,高校思路,就是再输入数据时进行求和,算区间和时,直接两个区间顶点值相减即可!
普通算法代码:

#include<bits/stdc++.h>
using namespace std;
long long sum(int x,int y,int a[])
{
    long long sum = 0; 
    for(int i=x;i<=y;i++)
    {
        sum = (a[i]+sum)%10000019;
    }
    return sum;
}
int main()
{
    int n;
    cin>>n;
    int a[10006];
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    long long t;
    cin>>t;
    while(t--)
    {
        int x,y;
        cin>>x>>y;
        long long ans = sum(x,y,a);
        cout<<ans<<endl;
    }
    return 0;
}

高效AC算法:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
	int n,i,k,x,y,a;
	cin>>n;
	long long sum[1000006]={0}; 
	for(i=1;i<=n;i++)
	{
		cin>>a;
		sum[i]=sum[i-1]+a;
	}
	cin>>k;
	for(i=1;i<=k;i++)
	{
		cin>>x>>y;
		cout<<(sum[y]-sum[x-1])%10000019<<endl;
	}
    return 0;
}

7-10 抽卡游戏

题目:
本题的灵感来源于一个古典的概率模型。Alice 在一个卡池里抽卡,里面有 x 张 s 卡和 y 张 a 卡,Alice 每次会不放回的随机从卡池中抽出一张卡。Bob 在一旁看 Alice 抽卡并对每次的结果进行预测:若卡池里 s 卡的数量多于 a 卡,Bob 会猜 Alice 抽出 s 卡。反之则会猜测 Alice 抽出 a 卡。但是如果当卡池里的两种卡的数量相等的时候,Bob 就不对抽卡的结果做任何的猜测了。Alice 会一直抽卡,直到卡池空为止。现在告诉你初始的时候卡池里 s 卡和 a 卡的数量,你能算算 Bob 期望下猜对多少次?

输入格式:
在一行中给出两个整数 a,b(1≤a,b≤10^​5​​ )

输出格式:
一个实数表示期望,四舍五入保存两位小数。

输入样例:
1 1
输出样例:
1.00
样例解释:
初始局面的时候 Bob 不做任何猜测,第一次抽完之后,第二次抽的时候不管剩下的是哪一种卡,Bob 都能猜对,所以期望是1.00
思路:
规律题,直接是max(a,b)
但在输出的时候应注意,保留两位小数,同时应该定义a,b数据类型为double
看推导过程:该题目其实很简单 答案就是max(a,b)
AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    double a,b;
    cin>>a>>b;
    cout<<fixed<<setprecision(2)<<max(a,b);
    return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CX__CS

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

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

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

打赏作者

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

抵扣说明:

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

余额充值