小陈的开学第一周程序

本文记录了小陈在开学第一周参加的编程竞赛,包括AtCoder的Attack Survival和Powerful Discount Tickets题目,PTA的魔法优惠券和最大子列和问题,以及计蒜客的Digit sum问题。文章详细介绍了题意、解题思路和代码实现过程,分享了从超时到通过AC的解决策略。
摘要由CSDN通过智能技术生成

一、AtCoder

1.Attack Survival

题意

Takahashi has decided to hold fastest-finger-fast quiz games. Kizahashi, who is in charge of making the scoreboard, is struggling to write the program that manages the players’ scores in a game, which proceeds as follows.

A game is played by N players, numbered 1 to N. At the beginning of a game, each player has K points.

When a player correctly answers a question, each of the other N−1 players receives minus one (−1) point. There is no other factor that affects the players’ scores.

At the end of a game, the players with 0 points
or lower are eliminated, and the remaining players survive.

In the last game, the players gave a total of Q correct answers, the i-th of which was given by Player Ai. For Kizahashi, write a program that determines whether each of the N players survived this game.
输出几轮得分后每个人是否存活下来

变量范围:

  1. All values in input are integers.
  2. 2≤N≤10^5
  3. 1≤K≤10^9
  4. 1≤Q≤10^5
  5. 1≤Ai≤N(1≤i≤Q)

输入

N K Q
A1
A2
.
.
.
AQ

输出

Print N lines. The i-th line should contain Yes if Player i survived the game, and No otherwise.

样例输入

6 3 4
3
1
3
2

样例输出

No
No
Yes
No
No
No

解题思路:

刚开始就是模拟题目的意思,但是超时了,后来用b数组记录一下他们得分的次数,就过了。

程序代码(TLE):

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int main(){
	int n,k,Q;
	cin>>n>>k>>Q;
	for(int i=1;i<=n;i++)
		a[i]=k;
	for(int i=1;i<=Q;i++){
		int temp;
		cin>>temp;
		for(int j=1;j<=n;j++){
			if(j!=temp)
				a[j]--;
		}
	}
	for(int i=1;i<=n;i++){
		if(a[i]<=0)
			cout<<"No"<<endl;
		else
			cout<<"Yes"<<endl;
	}
	return 0;
}

程序代码(AC):

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int b[N];
int main(){
	int n,k,Q;
	scanf("%d %d %d",&n,&k,&Q);
	for(int i=1;i<=Q;i++){
		int temp;
		scanf("%d",&temp);
		b[temp]++;
	}
	for(int i=1;i<=n;i++){
		a[i]=k-(Q-b[i]);
		if(a[i]<=0)
			printf("No\n");
		else
			printf("Yes\n");
	}
	return 0;
}

2.Powerful Discount Tickets

题意

Takahashi is going to buy N items one by one.

The price of the i-th item he buys is Ai yen (the currency of Japan).

He has M discount tickets, and he can use any number of them when buying an item.

If Y tickets are used when buying an item priced X yen, he can get the item for X/2^Y (rounded down to the nearest integer) yen.

What is the minimum amount of money required to buy all the items?
分配优惠卷,求最小支出

变量范围:

  1. All values in input are integers.
  2. 1≤N,M≤10^5
  3. 1≤Ai≤10^9

输入

N M
A1 A2 … AN

输出

Print the minimum amount of money required to buy all the items.

样例输入

3 3
2 13 8

样例输出

9

  1. We can buy all the items for 9 yen, as follows:
  2. Buy the 1-st item for 2 yen without tickets.
  3. Buy the 2-nd item for 3 yen with 2 tickets.
  4. Buy the 3-rd item for 4 yen with 1 ticket.

解题思路:

刚开始想的是取每次的最大值用优惠卷,所以每次都要重新sort,果然超时了,意料之中。后来想了很久(其实是听到了后面人的思路,嘻嘻),用了优先队列,就AC了。

程序代码:(TLE)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
bool cmp(int a,int b){
	return a>b;
}
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1,cmp);
	if(n==1){
		int flag=1;
		for(int i=1;i<=m;i++){
			a[1]/=2;
			if(a[1]<1){
				flag=0;
				printf("0\n");
				break;
			}
		}
		if(flag==1)
			printf("%d\n",a[1]);
	}else if(m==1){
		long long ans=a[1]/2;
		for(int i=2;i<=n;i++)
			ans += a[i];
		printf("%lld\n",ans);
	}else{
		for(int i=1;i<=m;i++){
			a[1]/=2;
			sort(a+1,a+n+1,cmp);
		}
		long long ans=0;
		for(int i=1;i<=n;i++)
			ans += a[i];
		printf("%lld\n",ans);
	}
	return 0;
}

程序代码:(AC)

#include<bits/stdc++.h>
using namespace std;
int main(){
	priority_queue<int>q;
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		int a;
		scanf("%d",&a);
		q.push(a);
	}
	for(int i=1;i<=m;i++){
		int temp=q.top();
		q.pop();
		temp/=2;
		q.push(temp);
	}
	long long ans=0;
	while(!q.empty()){
		int temp=q.top();
		q.pop();
		ans+=temp;
	}
	printf("%lld\n",ans);
	return 0;
}

二、PTA

1.魔法优惠券

题意

在火星上有个魔法商店,提供魔法优惠券。每个优惠劵上印有一个整数面值K,表示若你在购买某商品时使用这张优惠劵,可以得到K倍该商品价值的回报!该商店还免费赠送一些有价值的商品,但是如果你在领取免费赠品的时候使用面值为正的优惠劵,则必须倒贴给商店K倍该商品价值的金额…… 但是不要紧,还有面值为负的优惠劵可以用!(真是神奇的火星)

例如,给定一组优惠劵,面值分别为1、2、4、-1;对应一组商品,价值为火星币M$7、6、-2、-3,其中负的价值表示该商品是免费赠品。我们可以将优惠劵3用在商品1上,得到M$28的回报;优惠劵2用在商品2上,得到M$12的回报;优惠劵4用在商品4上,得到M$3的回报。但是如果一不小心把优惠劵3用在商品4上,你必须倒贴给商店M$12。同样,当你一不小心把优惠劵4用在商品1上,你必须倒贴给商店M$7。

规定每张优惠券和每件商品都只能最多被使用一次,求你可以得到的最大回报。

输入

输入有两行。第一行首先给出优惠劵的个数N,随后给出N个优惠劵的整数面值。第二行首先给出商品的个数M,随后给出M个商品的整数价值。N和M在[1, 10^​ 6​​ ]之间,所有的数据大小不超过2^​30​​ ,数字间以空格分隔。

输出

输出可以得到的最大回报。

样例输入

4 1 2 4 -1
4 7 6 -2 -3

样例输出

43

解题思路:

其实没有那么麻烦的,只用排一下序,让正的跟正的乘起来,负的跟负的乘起来就可以了。

程序代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
long long a[N],b[N];
bool cmp(long long a,long long b){
	return a>b;
}
int main(){
	int n,m;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i];
	cin>>m;
	for(int i=0;i<m;i++)
		cin>>b[i]; 
	sort(a,a+n);
	sort(b,b+n);
	long long ans=0;
	int mn=n>m?n:m;
	for(int i=0;i<mn;i++){
		if(a[i]<0&&b[i]<0){
			ans=ans+a[i]*b[i];
		}else
			break;
	}
	sort(a,a+n,cmp);
	sort(b,b+n,cmp);
	for(int i=0;i<mn;i++){
		if(a[i]>0&&b[i]>0){
			ans=ans+a[i]*b[i];
		}else
			break;
	}
	cout<<ans<<endl;
	return 0;
}

2.最大子列和问题

题意

给定K个整数组成的序列{ N1, N​2​​ , …, N​K​ },“连续子列”被定义为{ N​i​​ , N​i+1​​ , …, N​j​​ },其1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:与样例等价,测试基本正确性;
数据2:102个随机整数;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;

输入

输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。

输出

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

样例输入

6
-2 11 -4 13 -5 -2

样例输出

20

解题思路:

就是边加边比,这样就能找出最大的子列和。

程序代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int INF=0x3f3f3f3f;
int a[N];
int main(){
	int k;
	cin>>k;
	int flag=0;
	for(int i=1;i<=k;i++){
		cin>>a[i];
		if(a[i]>0)
			flag=1;
	}
	if(flag==0){
		cout<<0<<endl;
		return 0;
	}
	int max=-INF;
	for(int i=1;i<=k;i++){
		int sum=a[i];
		for(int j=i+1;j<=k;j++){
			if(sum>max) max=sum;
			sum+=a[j];
		}
		if(sum>max) max=sum;
	}
	cout<<max<<endl;
	return 0;
} 

三、计蒜客

1.Digit sum

题意

A digit sum S_b(n) is a sum of the base-b digits of n. Such as S_{10}(233) = 2 + 3 + 3 = 8,S_{2}(8)=1 + 0 + 0 = 1, S_{2}(7)=1 + 1 + 1 = 3

Given N and b, you need to calculate ∑(1-n)Sb(n)。

输入

The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line containing two integers N and b.

1≤T≤100000
1≤N≤10^6
2≤b≤10

输出

For each test case, output one line containing Case #x: y, where xx is the test case number (starting from 1) and y is answer.

样例输入

2
10 10
8 2

样例输出

Case #1: 46
Case #2: 13

解题思路

刚开始就是模拟输入的每个数,但是超时了。 后来经过老师的一番指导,用了打表,终于过了。

程序代码:(TLE)

#include<bits/stdc++.h>
using namespace std;
int main(){
	int T;
	scanf("%d",&T);
	int cnt=1;
	while(T--){
		int n,b;
		scanf("%d %d",&n,&b);
		int ans=0;
		for(int j=1;j<=n;j++){
			int k=j;
			while(k>0){
				ans=ans+(k%b);
				k/=b;
			}
		}
		printf("Case #%d: %d\n",cnt++,ans);
	}
	return 0;
}

程序代码:(AC)

#include<bits/stdc++.h>
#include<numeric>
using namespace std;
const int N=1e6;
int a[11][N+5];
int main(){
	for(int i=2;i<=10;i++){
		for(int j=1;j<=N;j++){
			int k=j;
			while(k>0){
				a[i][j]+=(k%i);
				k/=i;
			}
			a[i][j]+=a[i][j-1];
		}
	}
	int T;
	scanf("%d",&T);
	int cnt=1;
	while(T--){
		int n,b;
		scanf("%d %d",&n,&b);
//		int ans=0;
//		for(int j=1;j<=n;j++){
//			ans+=a[b][j];
//		}
		printf("Case #%d: %d\n",cnt++,a[b][n]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值