2023牛客寒假算法基础集训营5题解 4/12

< 已写:A 、B 、H 、 K>

更好的观看体验

其他的随后补

A - 小沙の好客

题目链接:小沙の好客
算法标签:【前缀和】【二分】
思路:先对商品的价格进行排序,然后进行前缀和操作,最后用二分函数upper_bound()找到第一个大于目标值的位置,遍历得出答案。
upper_bound()和lower_bound()的不同【@brandong】:

lower_bound(begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound(begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

代码
代码链接

#include 
#include 

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

ll a[N] , s[N];
int n , q;
int k , x;

void solve()
{
    scanf("%d%d",&k,&x);
    
    /*二分找到目标值所在位置,减去数组初始位置,则为目标值下标*/
    int r = upper_bound(a+1,a+n+1,x) - (a+1);
    int l = max(0,r - k + 1);
    
    /*利用前缀和,得出答案*/
    printf("%lld\n",s[r] - s[l - 1]);
}

int main()
{
    scanf("%d%d",&n,&q);
    
    for(int i = 1;i <= n;i ++)
        scanf("%lld",&a[i]);
    
    sort( a+1 , a+1+n );
    
    for(int i = 1;i <= n;i ++)
        s[i] = s[i - 1] + a[i];
    
    while( q-- )
        solve();
    
    return 0;
}

B - 小沙の博弈

题目链接:小沙の博弈
算法标签:【贪心】?(bushi)
思路:小沙和小雅两人分别取石子,小沙先取。每个人要使自己的字典序最小的话,每次只取一个,构成字典序:111...

  • 如果石子的个数是偶数的话,每个人取到的石子数相同,平局。
  • 如果石子的个数是奇数的话,小沙比小雅多取一个 (小沙先取!),因此小雅获胜。

代码
代码链接

#include 

using namespace std;

int main()
{
    int n;
    cin >> n;
    
    if(n % 2 == 0)
        puts("win-win!");
    else
        puts("Yaya-win!");
    
    return 0;
}

H - 小沙の店铺

题目链接:小沙の店铺
算法标签:【模拟】
思路:每次售出时,可以用cnt来记录共售卖的货品数,以便得到上涨后的价格。

  • 注意开long long

代码
代码链接

#include 

using namespace std;

typedef long long ll;

int main()
{
	ll x , y , k , n , t;
	scanf("%lld %lld %lld %lld %lld",&x,&y,&k,&n,&t);
	// x : 初始价格 
	// y : 每次上涨价格
	// k : 卖出k个物品,涨价
	// n : 共有n个客户
	// t : gmv
	
	ll pri = x; // 目前的价格
	ll sum = 0; // 收入
	ll cnt = 0; // 已售出的货物数量
	
	ll i;
	for(i = n;i >= 1;i --)
	{
		sum += pri*i; // 计算收入
		
		cnt += i;
		pri = x + (cnt/k) * y; // 计算涨价后的价格
		
		if(sum >= t) // 如果达到目标值,直接退出
			break;
	}
	
	if(sum < t) // 如果所有的顾客都已购买后,仍未达到目标值,输出-1
		printf("-1\n");
	else
		printf("%lld\n",n-i+1);
	
	return 0;
}

K - 小沙の抱团 easy

题目链接:小沙の店铺
算法标签:【模拟】【贪心】
思路:每次使得淘汰的人数最多,所需要的指令就越少

  • 当场上的人数是偶数时,那么就抱团(人数/2+1),使得淘汰的人数最多
  • 当场上的人数是奇数时,抱团(奇数/2)向上取整 --> (奇数+1)/2,使得淘汰的人数最多

代码
代码链接

#include 
#include 

using namespace std;

typedef long long ll;

int main()
{
	ll n;
	scanf("%lld",&n);
	
	ll ans = 0; // 存放指令个数
	
	while(n > 2)
	{
		if( n%2 ) //奇数时
			n = (n+1) / 2;
		else //  偶数时
			n = n / 2 + 1;
		
		ans ++;
	}
	
	printf("%lld\n",ans);
	return 0;
}

你可能感兴趣的:(牛客比赛,算法,c++,图论)