A P6363 软件工程实习
题目描述
某大学的《软件工程》必修课分为理论和实践部分。理论部分由该校教授完成授课;而实践部分是由第三方的公司主导,需要同学们在五周时间内自学 HTML、css、JavaScript、vue、Python、django 等技术,并组队完成一个真实的互联网商业应用。
参与这个课程的有 n(0≤n≤1000) 个学生,分成了不超过26个队伍,每个队伍用 A到Z来表示。每个队伍都会完成一个项目,并以队伍为单位,给所有队伍(包括自己队伍)打分,范围是 0到100 的整数。
为了平息学生对这门课产生的出多问题的不满(比如工作量太大、时间过于紧张、考核方式不公平等),老师决定使用一种“看起来”很公平的方式来决定每组队伍的项目得分:
对于某个队伍,首先计算所有队伍(包括自己)给这个队伍评分的平均值,然后剔除掉和这个平均值差别超过 15 分的评分(保证不会出现所有的评分全部被剔除的情况),最后再对剩余的评分求平均值,四舍五入取整后作为这个队伍的项目得分。
对于每一个同学,我们已经得知他们的队伍代号和理论成绩(也是 0 到 100分的整数)。这位同学的最后得分就是 60% 的理论成绩加上40% 的所在队伍的项目得分,然后四舍五入取整。
现在老师想知道所有同学的分数排行。请按最后得分从高到低的顺序,输出每位同学的得分和他所在的队伍。
输入格式
第一行两个整数 n 和 k,分别表示学生数和队伍数。接下来 n 行,每行一个整数 si 和一个大写字母ci,表示第 i个选手的理论分数和队伍编号。保证队伍编号范围是从 A 开始后连续 k个字母中的一个。接下来 k行,每行 k 个整数。其中第 i 行第 j 列的整数 a ij表示第 i 个队伍给第 j个队伍的评分,当 i==j 时,就是自评。
输出格式
输出 n行表示答案,得分高的同学优先输出,得分相同时队伍编号较小的同学优先输出。对于每一行,先输出这位同学成绩,然后输出代表他的队伍编号的大写英文字母。
输入 #1
6 3
70 A
80 A
65 B
95 B
85 C
90 C
70 90 100
95 88 85
30 47 100
输出 #1
93 B
92 C
89 C
76 A
75 B
70 A
说明/提示
A 组收到的分数分别是 70,95,30,其平均分为 65,则 95,30被作为无效成绩剔除,因此 A 组的项目得分是 70 分。
B 组收到的分数分别是 90,88,47其平均分为 75,则 47 被作为无效成绩剔除,因此 B 组的项目得分是 89 分。
C 组收到的分数分别是 100,85,100,其平均分为 95,没有打分被剔除,因此 C 组的项目得分是 95 分。
代码
//需要注意的点都在上面文章加粗了的,也就是需要二次四舍五入,一个按照分数排序和字典序排序。
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
double mapp[10000][10000];
double dui[10000][10000];
double PT[10000];
int len[10000];
struct sm{
int X;
char Y;
}MM[10000];
int cmp(sm a,sm b){
if(a.X==b.X)
return a.Y<b.Y;
else
return a.X>b.X;
}
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
int a;
char b;
scanf("%d %c",&a,&b);
dui[b-'A'][len[b-'A']++]=a;
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
cin>>mapp[i][j];
}
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
PT[i-1]+=mapp[j][i];
}
PT[i-1]=1.0*PT[i-1];
}
for(int i=1;i<=k;i++)
{
int ansk=0;
double NB=0;
for(int j=1;j<=k;j++)
{
double FF=(1.0*PT[i-1]/k-mapp[j][i]);
if(FF<0)
FF=-FF;
if(FF>15.0)
{
ansk++;
NB+=(mapp[j][i]);
}
}
PT[i-1]=1.0*(PT[i-1]-NB)/(k-ansk);
int TP=(int)(PT[i-1]+0.5);
PT[i-1]=TP;
}
int F=0;
for(int j=0;j<k;j++)
{
for(int L=0;L<len[j];L++)
{
dui[j][L]=(int)(dui[j][L]*0.6+PT[j]*0.4+0.5);
MM[F].X=dui[j][L];
MM[F++].Y=char('A'+j);
}
}
sort(MM,MM+F,cmp);
for(int i=0;i<F;i++)
{
cout<<MM[i].X<<" "<<MM[i].Y<<endl;
}
return 0;
}
B P6364 1024 程序员节发橙子
展开
题目描述
每年的 1024 程序员节日,黑马程序员都会举办大型的庆祝活动。今年的程序员节也不例外,每个班级的同学都发了橙子。
班级里有 nnn 名同学从前到后排成一排,且已经得知了这些同学的成绩,其中第 iii 名同学的成绩是 aia_iai。班主任想根据同学们上个阶段的考试成绩来评定发橙子的数量。为了激励成绩优秀同学,发橙子时需要满足如下要求:
- 相邻同学中成绩好的同学的橙子必须更多。若相邻的同学成绩一样,则它们分到的数量必须平等。
- 每个同学至少分配一个橙子
由于预算有限,班主任希望在符合要求的情况下发出尽可能少的橙子。请问,至少需要准备多少橙子呢?
输入格式
第一行是一个不超过 10610^6106 正整数 nnn,表示学生数量。
接下来一行有 nnn 个不超过 10910^9109 的非负整数 aia_iai,表示第 iii 个同学的成绩。
输出格式
输出答案,也就是需要最少准备多少个橙子。
输入输出样例
5 3 4 5 4 3
9
说明/提示
样例解释:
每位同学拿到的橙子的数量分别是 1,2,3,2,11,2,3,2,11,2,3,2,1,所以至少需要准备 999 个。
代码
在这里插入代码片
//贪心算法 初始化为一,然后正反二次遍历取最大 保证满足要求 这题需要开long long
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
using namespace std;
int main(){
int n;
cin>>n;
ll ans=0;
vector<ll>arr(n);
vector<ll>A(n,1);
vector<ll>B(n,1);
for(int i=0;i<n;i++){
cin>>arr[i];
}
for(int i=1;i<n;i++)
{
if(arr[i]>arr[i-1])
{
A[i]=A[i-1]+1;
}
}
ans+=A[n-1];
for(int i=n-2;i>=0;i--)
{
if(arr[i]>arr[i+1])
{
B[i]=B[i+1]+1;
}
ans+=max(A[i],B[i]);
}
cout<<ans<<endl;
return 0;
}
C P6365 众数出现的次数
题目描述
传智专修学员的课堂上,为了活跃气氛,并巩固位运算的知识,同学们玩起了一个游戏。
班级里有 n(n≤106)n(n\le10^6)n(n≤106) 名同学,每位同学都获得了两张卡,红卡或者黑卡。每张卡上都有一个不超过 10910^9109 的非负整数。第 iii 位同学手里红卡数字是 aia_iai ,黑卡数字是 bib_ibi。
现在需要每位同学出牌。每位同学可以直接将红卡上的数字打出,或者将自己的红卡上的数字和自己黑卡数字进行按位异或操作后的结果打出。最后老师会收集所有同学打出的数字。
这些数字中出现次数最多的数字是众数。在所有同学合作的最优策略下,我们希望众数对应数字出现的次数尽可能多。请问出现次数最多的数字是多少呢?
输入格式
第一行,一个正整数 nnn。
接下来 nnn 行,其中第 iii 行时非负整数 ai,bia_i,b_iai,bi 代表第 iii 名同学手上红卡和黑卡的数字。
输出格式
一个整数,表示答案。如果有多个解,请输出最小的那个。
输入输出样例
4 21 9 28 9 28 3 17 4
21
说明/提示
样例解释:
众数出现次数最多是 333 次,有如下两种方法:
- 111 号同学直接出红卡,222 号同学出红黑异或,333 号同学随便出,444 号同学出红黑异或。这样 1,2,41,2,41,2,4 号同学都可以打出 212121。
- 111 号同学出红黑异或,222 号同学直接出红卡,333 号同学直接出红卡,444 号同学随便出。这样 1,2,31,2,31,2,3 号同学都可以打出 282828。
所以 212121 和 282828 都是出现次数最多的众数,因为最多可以出现 333 次,不存在出现 444 次的方案。但是由于要求如果有多解输出小的,请输出 212121。
代码
//判断就可以了
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N =1000005;
map<int,int>Map;
int a[N],b[N],n;
int tag=0;
int ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],cin>>b[i],b[i]^=a[i]; //出红黑异或
for(int i=1;i<=n;i++){
if(a[i]!=b[i]){ //如果二种一样只能出一种
Map[a[i]]++;
Map[b[i]]++;
}else{
Map[a[i]]++;
}
}
for(map<int,int>::iterator it = Map.begin();it!=Map.end();it++){
if(it->second>ans){ //众数
ans=it->second;
tag=it->first;
}else if(it->second== ans && it->first<tag){ //最小的众数
tag=it->first;
}
}
cout<<tag<<endl;
return 0;
}