一、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.
输出几轮得分后每个人是否存活下来
变量范围:
- All values in input are integers.
- 2≤N≤10^5
- 1≤K≤10^9
- 1≤Q≤10^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?
分配优惠卷,求最小支出
变量范围:
- All values in input are integers.
- 1≤N,M≤10^5
- 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
- We can buy all the items for 9 yen, as follows:
- Buy the 1-st item for 2 yen without tickets.
- Buy the 2-nd item for 3 yen with 2 tickets.
- 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, N2 , …, NK },“连续子列”被定义为{ Ni , Ni+1 , …, Nj },其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;
}