L2-002. 链表去重
给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点。即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留。同时,所有被删除的结点必须被保存在另外一个链表中。例如:另L为21→-15→-15→-7→15,则你必须输出去重后的链表21→-15→-7、以及被删除的链表-15→15。
输入格式:
输入第一行包含链表第一个结点的地址、以及结点个数N(<= 105 的正整数)。结点地址是一个非负的5位整数,NULL指针用-1表示。
随后N行,每行按下列格式给出一个结点的信息:
Address Key Next
其中Address是结点的地址,Key是绝对值不超过104的整数,Next是下一个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除结点组成的链表。每个结点占一行,按输入的格式输出。
输入样例:00100 5 99999 -7 87654 23854 -15 00000 87654 15 -1 00000 -15 99999 00100 21 23854输出样例:
00100 21 23854 23854 -15 99999 99999 -7 -1 00000 -15 87654 87654 15 -1
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=100005;
struct Node
{
int key;
int next;
}aa[maxn];
int ans[maxn],res[maxn],vis[maxn];
int main()
{
int fadd,n;
scanf("%d%d",&fadd,&n);
int add;
for(int i=0;i<n;i++)
{
scanf("%d",&add);
scanf("%d%d",&aa[add].key,&aa[add].next);
}
int t1=0,t2=0;
for(int i=fadd;i!=-1;i=aa[i].next)
{
int num=abs(aa[i].key);
if(!vis[num])
{
vis[num]=1;
ans[t1++]=i;
}
else
res[t2++]=i;
}
printf("%05d %d ",ans[0],aa[ans[0]].key);
for(int i=1;i<t1;i++)
{
printf("%05d\n",ans[i]);
printf("%05d %d ",ans[i],aa[ans[i]].key);
}
printf("-1\n");
if(t2)
{
printf("%05d %d ",res[0],aa[res[0]].key);
for(int i=1;i<t2;i++)
{
printf("%05d\n",res[i]);
printf("%05d %d ",res[i],aa[res[i]].key);
}
printf("-1\n");
}
return 0;
}
L2-003. 月饼
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:3 20 18 15 10 75 72 45输出样例:
94.50
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct P
{
double a;
double b;
double c;
};
bool cmp(P A,P B)
{
return A.c>B.c;
}
int main()
{
int N,D;
P a[1005];
while(scanf("%d%d",&N,&D)!=EOF)
{
for(int i=0;i<N;i++)
scanf("%lf",&a[i].a);
for(int i=0;i<N;i++)
{
scanf("%lf",&a[i].b);
a[i].c=a[i].b/a[i].a;
}
sort(a,a+N,cmp);
double sum=0;
for(int i=0;D!=0;i++)
{
if(a[i].a>D)
{
sum+=a[i].c*D;
D=0;
}
else
{
sum+=a[i].b;
D-=a[i].a;
}
}
printf("%.2lf\n",sum);
}
return 0;
L2-005. 集合相似度
给定两个整数集合,它们的相似度定义为:Nc/Nt*100%。其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
输入格式:
输入第一行给出一个正整数N(<=50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(<=104),是集合中元素的个数;然后跟M个[0, 109]区间内的整数。
之后一行给出一个正整数K(<=2000),随后K行,每行对应一对需要计算相似度的集合的编号(集合从1到N编号)。数字间以空格分隔。
输出格式:
对每一对需要计算的集合,在一行中输出它们的相似度,为保留小数点后2位的百分比数字。
输入样例:3 3 99 87 101 4 87 101 5 87 7 99 101 18 5 135 18 99 2 1 2 1 3输出样例:
50.00% 33.33%
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
set<int> s[55];
int n,m,x;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&m);
for(int j=0;j<m;j++)
{
scanf("%d",&x);
s[i].insert(x);
}
}
int k;
scanf("%d",&k);
while(k--)
{
int y1,y2;
scanf("%d%d",&y1,&y2);
set<int>::iterator aa;
int sam=0;
for(aa=s[y1].begin();aa!=s[y1].end();aa++)
{
if(s[y2].find(*aa)!=s[y2].end())
sam++;
}
double mm=sam*1.0/(s[y1].size()+s[y2].size()-sam);
printf("%.2lf%%\n",mm*100);
}
return 0;
}
L2-010. 排座位
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
输入格式:
输入第一行给出3个正整数:N(<= 100),即前来参宴的宾客总人数,则这些人从1到N编号;M为已知两两宾客之间的关系数;K为查询的条数。随后M行,每行给出一对宾客之间的关系,格式为:“宾客1 宾客2 关系”,其中“关系”为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K行,每行给出一对需要查询的宾客编号。
这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。
输出格式:
对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出“No problem”;如果他们之间并不是朋友,但也不敌对,则输出“OK”;如果他们之间有敌对,然而也有共同的朋友,则输出“OK but...”;如果他们之间只有敌对关系,则输出“No way”。
输入样例:7 8 4 5 6 1 2 7 -1 1 3 1 3 4 1 6 7 -1 1 2 1 1 4 1 2 3 -1 3 4 5 7 2 3 7 2输出样例:
No problem OK OK but... No way
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<string>
#include<algorithm>
using namespace std;
int fa[105];
int mm[105][105];
int find(int x)
{
if(x!=fa[x])
fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int i1,i2,t;
scanf("%d%d%d",&i1,&i2,&t);
if(t==1)
{
int a=find(i1);
int b=find(i2);
if(a==b)
continue;
if(a<b)
fa[b]=a;
else
fa[a]=b;
}
else
mm[i1][i2]=mm[i2][i1]=t;
}
for(int i=0;i<k;i++)
{
int i1,i2;
scanf("%d%d",&i1,&i2);
int a=find(i1);
int b=find(i2);
if(a==b&&mm[i1][i2]!=-1)
printf("No problem\n");
else if(a==b&&mm[i1][i2]==-1)
printf("OK but...\n");
else if(a!=b&&mm[i1][i2]!=-1)
printf("OK\n");
else
printf("No way\n");
}
return 0;
}
L2-015. 互评成绩
学生互评作业的简单规则是这样定的:每个人的作业会被k个同学评审,得到k个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。本题就要求你编写这个互评系统的算分模块。
输入格式:
输入第一行给出3个正整数N(3< N <= 104,学生总数)、k(3<= k <= 10,每份作业的评审数)、M(<= 20,需要输出的学生数)。随后N行,每行给出一份作业得到的k个评审成绩(在区间[0, 100]内),其间以空格分隔。
输出格式:
按非递减顺序输出最后得分最高的M个成绩,保留小数点后3位。分数间有1个空格,行首尾不得有多余空格。
输入样例:6 5 3 88 90 85 99 60 67 60 80 76 70 90 93 96 99 99 78 65 77 70 72 88 88 88 88 88 55 55 55 55 55输出样例:
87.667 88.000 96.000
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int aa[10010][20];
double sum[10010];
int main()
{
int n,k,m;
scanf("%d%d%d",&n,&k,&m);
for(int i=0;i<n;i++)
for(int j=0;j<k;j++)
scanf("%d",&aa[i][j]);
for(int i=0;i<n;i++)
{
sort(aa[i],aa[i]+k);
for(int j=1;j<k-1;j++)
sum[i]+=1.0*aa[i][j];
sum[i]/=k-2;
}
sort(sum,sum+n);
printf("%.3lf",sum[n-m]);
for(int i=n-m+1;i<n;i++)
printf(" %.3lf",sum[i]);
printf("\n");
return 0;
}
L2-017. 人以群分
社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。
输入格式:
输入第一行给出一个正整数N(2 <= N <= 105)。随后一行给出N个正整数,分别是每个人的活跃度,其间以空格分隔。题目保证这些数字以及它们的和都不会超过231。
输出格式:
按下列格式输出:
Outgoing #: N1 Introverted #: N2 Diff = N3
其中 N1 是外向型人的个数;N2 是内向型人的个数;N3 是两群人总活跃度之差的绝对值。
输入样例1:10 23 8 10 99 46 2333 46 1 666 555输出样例1:
Outgoing #: 5 Introverted #: 5 Diff = 3611输入样例2:
13 110 79 218 69 3721 100 29 135 2 6 13 5188 85输出样例2:
Outgoing #: 7 Introverted #: 6 Diff = 9359
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int ss[100005];
int main()
{
int n,i,sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&ss[i]);
sum+=ss[i];
}
sort(ss,ss+n);
int n2=n/2;
int n1=n-n2;
int sum1=0;
for(int i=0;i<n2;i++)
sum1+=ss[i];
int Diff=sum-2*sum1;
printf("Outgoing #: %d\nIntroverted #: %d\n",n1,n2);
printf("Diff = %d\n",Diff);
return 0;
}
L2-019. 悄悄关注
新浪微博上有个“悄悄关注”,一个用户悄悄关注的人,不出现在这个用户的关注列表上,但系统会推送其悄悄关注的人发表的微博给该用户。现在我们来做一回网络侦探,根据某人的关注列表和其对其他用户的点赞情况,扒出有可能被其悄悄关注的人。
输入格式:
输入首先在第一行给出某用户的关注列表,格式如下:
人数N 用户1 用户2 …… 用户N
其中N是不超过5000的正整数,每个“用户i”(i=1, ..., N)是被其关注的用户的ID,是长度为4位的由数字和英文字母组成的字符串,各项间以空格分隔。
之后给出该用户点赞的信息:首先给出一个不超过10000的正整数M,随后M行,每行给出一个被其点赞的用户ID和对该用户的点赞次数(不超过1000),以空格分隔。注意:用户ID是一个用户的唯一身份标识。题目保证在关注列表中没有重复用户,在点赞信息中也没有重复用户。
输出格式:
我们认为被该用户点赞次数大于其点赞平均数、且不在其关注列表上的人,很可能是其悄悄关注的人。根据这个假设,请你按用户ID字母序的升序输出可能是其悄悄关注的人,每行1个ID。如果其实并没有这样的人,则输出“Bing Mei You”。
输入样例1:10 GAO3 Magi Zha1 Sen1 Quan FaMK LSum Eins FatM LLao 8 Magi 50 Pota 30 LLao 3 Ammy 48 Dave 15 GAO3 31 Zoro 1 Cath 60输出样例1:
Ammy Cath Pota输入样例2:
11 GAO3 Magi Zha1 Sen1 Quan FaMK LSum Eins FatM LLao Pota 7 Magi 50 Pota 30 LLao 48 Ammy 3 Dave 15 GAO3 31 Zoro 29输出样例2:
Bing Mei You
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
struct MM
{
char nam[10];
int a;
};
char s[5005][10];
MM ss[10005];
bool cmp(MM A,MM B)
{
if(strcmp(A.nam,B.nam)<0)
return true;
return false;
}
int main()
{
int N;
scanf("%d",&N);
getchar();
map<string,bool> mmp;
for(int i=0;i<N;i++)
{
scanf("%s",&s[i]);
mmp[s[i]]=true;
}
int M;
scanf("%d",&M);
getchar();
int sum=0;
for(int i=0;i<M;i++)
{
scanf("%s %d",ss[i].nam,&ss[i].a);
sum+=ss[i].a;
}
sum/=M;
sort(ss,ss+M,cmp);
int ff=0;
for(int i=0;i<M;i++)
{
if(ss[i].a>sum&&!mmp[ss[i].nam])
{
ff=1;
printf("%s\n",ss[i].nam);
}
}
if(ff==0)
printf("Bing Mei You\n");
return 0;
}