2020牛客NOIP赛前集训营-普及组(第二场) 题解

it2024-06-25  43

目录

T1 面试描述题目描述输入描述:输出描述: 题解代码 T2 纸牌游戏描述题目描述输入描述:输出描述: 题解代码 T3 涨薪描述题目描述输入描述:输出描述: 题解代码 T4描述题目描述输入描述:输出描述: 题解代码

T1 面试

描述

题目描述

牛牛内推了好多人去牛客网参加面试,面试总共分四轮,每轮的面试官都会对面试者的发挥进行评分。评分有 A B C D 四种。如果面试者在四轮中有一次发挥被评为 D,或者两次发挥被评为 C,就不会通过面试。如果面试者没有一次被评为 D,并且有三个或以上的 A,则会获得 special offer。其余情况会获得普通 offer。

现在告诉你一些面试者的发挥,请你算一算,他们的面试结果分别是什么。

输入描述:

第一行输入一个 T,代表面试者的个数。

接下来有 T 行,每行都有一个长度为 4 的字符串,每个位置的字符分别代表面试者每一轮的发挥。

输出描述:

输出 T 行,分别表示 T 个面试者的面试结果。如果面试失败,输出failed,如果面试通过,但不是 special offer,则输出offer,否则输出 sp offer。

题解

人口普查

代码

#include<bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ char a[15]; scanf("%s",a+1); int ans1=0,ans2=0; bool f=0; for(int j=1;j<=4;j++){ if(a[j]=='C'){ ans1++; } if(a[j]=='D'){ f=1; } if(a[j]=='A'){ ans2++; } } if(f||ans1>=2){ printf("failed\n"); continue; } if(ans2>=3&&f==0){ printf("sp offer\n"); continue; } printf("offer\n"); } return 0; }

T2 纸牌游戏

描述

题目描述

公司举办团建活动,许多人在一起玩一个纸牌游戏。规则如下:

总共有 n 个人,每个人初始有 n 张牌。每一轮从第一个人开始轮流操作,第 i 个人每次操作必须选min(people-1,ai) 个不同的人,分别从他们手中拿走一张牌。其中people 为游戏现存人数,手上没有牌的人立即被淘汰出局。大家希望有尽可能多的人出局,游戏无限的进行下去,问最终游戏中最少还有几个人没有出局。

注意:不能从自己手中拿牌

输入描述:

第一行输入一个数字 n, 代表游戏的总人数。接下来输入 n 个数字,分别代表 ai ​

输出描述:

输出一行一个整数表示游戏最终最少剩几个人。

题解

贪心

对于每个人,如果他现在可以抽取的牌数小于当前人数-1,则他一定会被别人淘汰

如果现在的所有人都可以抽取当前人数-1张牌,那么游戏就可以无限进行下去

代码

#include<bits/stdc++.h> using namespace std; int n; int a[100005]; priority_queue <int,vector<int>,greater<int> > q; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); q.push(a[i]); } while(n>1){ int x=q.top(); if(x>=n-1){ printf("%d",n); return 0; } else{ q.pop(); n--; } } printf("%d",n); return 0; }

T3 涨薪

描述

题目描述

公司中总共有 n 个人,其中第 i 个人的初始工资为 ai 。公司根据每个人的绩效(工作表现)来评定每个人的涨薪幅度。每年有 x 个人绩效为 A,工资可以变为原来的 3 倍;y 个人绩效为 B,工资可以变为原来的 2 倍,其余人绩效为 C,工资不变,连续两年绩效为 C 会被开除。

假如公司没有一直招聘新员工,请问 m 年后,公司需要给所有在职员工支付的工资总和最多为多少。由于答案可能很大,请输出对 10^9+7 取模后的结果。

输入描述:

输入第一行包含四个正整数 n, m,x,y,意义如题面所示。

接下来一行包含 n 个正整数,第 i 个正整数为 ai ​ 代表第 i 个人的初始工资。

输出描述:

输出一行一个整数表示 m 年后工资总和对 10^9+7 取模后的结果。

题解

贪心易得,绩效得C 的人一定是初始薪资最少的人。

其余的人进行排序,最大的x个和次大的y个分别乘3和2,其余的都不要;

因为有m天,每天都是乘同样的数,所以快速幂;

值得注意的是,如果m==1,则所有的人都不会被开除,需要特判;

代码

#include<bits/stdc++.h> using namespace std; const long long Mod=1e9+7; long long a[100005]; bool cmp(long long a,long long b){ return a>b; } long long Pow(long long a,int b){ long long ans=1; while(b){ if(b&1){ ans=ans*a%Mod; } a=a*a%Mod; b>>=1; } return ans; } long long sum=0; int main(){ int n,m,x,y; scanf("%d%d%d%d",&n,&m,&x,&y); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); sum=sum+a[i]%Mod; } sort(a+1,a+n+1,cmp); int len=0; long long sum1=0,sum2=0; while(len<x){ sum1=sum1+a[++len]%Mod; } while(len<x+y){ sum2=sum2+a[++len]%Mod; } sum=sum-sum1-sum2; sum1=sum1*Pow(3,m)%Mod; sum2=sum2*Pow(2,m)%Mod; if(m==1){ sum1=sum1+sum%Mod; } printf("%lld",(sum1+sum2)%Mod); return 0; }

T4

描述

题目描述

给出一个序列A,其中第 i 个数字为 ai,你每次操作可以选择一个数字不变,其他数字乘以 x,其中 x 为任意素数

无需考虑这些数字在变换过程中是否超过 long long 的存储范围。请回答:最少经过多少次操作,可以使得序列中所有数字全部相同。

输入描述:

第一行包含一个正整数 n,代表序列长度。

接下来一行包含 n 个正整数,描述序列中的每一个元素。

输出描述:

输出一行一个正整数表示答案。

题解

对于任何一列数来说,选取一个数,让其它数乘一个素数其实就等价于让选取的数除以一个素数,所以这道题就转换为如下题目:

给定一个序列,其中第 i 个数字为 ai,你每次操作可以选择一个数字除以x,x为任意素数,请问最少经过多少次操作,可以使得序列中所有数字全部相同。

让所有数字相同,即使所有数字的GCD,于是它又可以转换为如下题目:

给定一个序列,其中第 i 个数字为 ai,你每次操作可以选择一个数字除以x,x为任意素数,请问最少经过多少次操作,才可以让每个数都变成所有原数的GCD。

所以就很简单了,分解序列中每个数的质因数,除去GCD,相加

代码

#include<bits/stdc++.h> using namespace std; int Prime[10005]; bool f[1000005]; int n; int a[1000005]; void In_prime(){ for(int i=2;i<=1e3;i++){ if(!f[i]) Prime[++Prime[0]]=i; for(int j=0;j<Prime[0]&&i*Prime[j]<=1e3;j++) f[i*Prime[j]]=1; } } int GCD(int a,int b){ if(b==0){ return a; } return GCD(b,a%b); } int main(){ In_prime(); cin>>n; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int sum=a[1]; for(int i=2;i<=n;i++){ sum=GCD(sum,a[i]); } for(int i=1;i<=n;i++){ a[i]/=sum; } int tot=0; for(int i=1;i<=n;i++){ for(int j=1;j<=Prime[0]&&Prime[j]*Prime[j]<=a[i];j++){ while(a[i]%Prime[j]==0){ tot++; a[i]/=Prime[j]; } } if(a[i]!=1){ tot++; } } printf("%d\n",tot); return 0; }
最新回复(0)