第一周周记(2022.07.15-2022.07.16)

目录

(一)ACM入门练习
A-Download Manager 
Input
Output
Sample Input
Sample Output
理解
AC代码
B-sort
Input
Output
Sample Input
Sample Output
理解
AC代码
C-人见人爱A-B
Input
Output
Sample Input
Sample Output
理解
AC代码
D-人见人爱A^B
Input
Output
Sample Input
Sample Output
理解
AC代码

(二)牛客周赛round3

A-游游的7的倍数
Input
Output
Sample Input
Sample Output
理解
AC代码
B-游游的字母串
Input
Output
Sample Input
Sample Output
理解
AC代码
C-游游的水果大礼包

Input
Output
Sample Input
Sample Output
理解
AC代码
D-游游的权值矩阵
Input
Output
Sample Input
Sample Output
理解
AC代码

(三)知识

(1)用输出中间结果的方法调试
(2)用重定向的方式读写文件
(3)用fopen的方式读写文件


(一)例题记录

A-Download Manager

Jiajia downloads a lot, a lot more than you can even imagine. Some say that he starts downloading up to 20,000 files together. If 20,000 files try to share a limited bandwidth then it will be a big hazard and no files will be downloaded properly. That is why, he uses a download manager.

If there are T files to download, the download manger uses the following policy while downloading files:

1. The download manager gives the smaller files higher priority, so it starts downloading the smallest n files at startup. If there is a tie, download manager chooses the one with less bytes remaining (for download). We assume that with at least 50 Mega Bytes/sec of bandwidth, n files can be downloaded simultaneously without any problem.

2. The available bandwidth is equally shared by the all the files that are being downloaded. When a file is completely downloaded its bandwidth is instantaneously given to the next file. If there are no more files left except the files that are being downloaded, this bandwidth is immediately shared equally by all remaining files that are being downloaded.

Given the size and completed percentage of each file, your task is to intelligently simulate the behavior of the download manager to find the total time required to download all the files.

Input

The will be at most 10 test cases. Each case begins with three integers T (1 <= T <= 20000), n (1 <= n <= 2000 and 1 <= n <= T) and B (50 <= B <= 1000). Here B denotes the total bandwidth available to Jiajia (In Megabytes/sec). Please note that the download manager always downloads n files in parallel unless there are less than n files available for download. Each of next T lines contains one non-negative floating-point number S (less than 20,000, containing at most 2 digits after the decimal places) and one integer P (0 <= P <= 100). These two numbers denote a file whose size is S megabyte and which has been downloaded exactly P% already. Also note that although theoretically it is not possible that the size of a file or size of its remaining part is a fraction when expressed in bytes, for simplicity please assume that such thing is possible in this problem. The last test case is followed by T=n=B=0, which should not be processed.

Output

For each case, print the case number and the total time required to download all the files, expressed in hours and rounded to 2 digits after the decimal point. Print a blank line after the output of each test case.

Sample Input

6 3 90
100.00 90
40.40 70
60.30 70
40.40 80
40.40 85
40.40 88
1 1 56
12.34 100
0 0 0

Sample Output

Case 1: 0.66

Case 2: 0.00

理解

1.题目给出的T,n,B分别表示:给出的文件个数,可以同时下载的文件个数上限,下载速度上限(会平均分配给所有的下载任务,所以n可以忽略)。

2.接下来给出的是T个文件的大小,以及已下载百分比。

3.所以只需要求出T个文件的剩余下载量的总和,再除以下载速度B,即得出答案。

AC代码

#include<stdio.h>
int main()
{
	int t,n,b,c=0;
	while(scanf("%d %d %d",&t,&n,&b)!=EOF)
	{
		if(t==0&&n==0&&b==0)
		{
			break;
		}
		double s;
		int p;
		double sum=0;
		double a[20005];
		for(int i=0;i<t;i++)
		{
			scanf("%lf%d",&s,&p);
			sum=sum+s*(1-p/100.00);
		}
		c++;
		printf("Case %d:",c);
		printf("%.2f\n",sum/(double)b);
	}
	return 0;
}

B-sort

给你n个整数,请按从大到小的顺序输出其中前m大的数。

Input

每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数。

Output

对每组测试数据按从大到小的顺序输出前m大的数。

sample input

5 3
3 -35 92 213 -644

sample output

213 92 3

理解

1.因为数组里不能是负数,所以每个数都先加上500000,输出时再减去500000

2.在根据谁接近上限输出谁,输到第m个中止。

AC代码

#include<stdio.h>
#include<string.h>
const int N=1e6+5;
int a[N];
int main()
{
	int n,m;
	while(~scanf("%d %d",&n,&m)){
	    for(int i=0;i<n;i++){
		    int x;
		    scanf("%d",&x);
		    a[x+500000]++;
	    }
	    int k=0;
	    for(int i=1000000;i>=0;i--){
		    if(a[i]){
			    printf("%d",i-500000);
			    k++;
			    if(k==m){
				    printf("\n");
			     break;	
			    }
			    else{
				    printf(" ");
			    }
		    }
	    }
	}
}

C-人见人爱的A-B

参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的差,就是做集合的减法运算。(当然,大家都知道集合的定义,就是同一个集合中不会有两个相同的元素,这里还是提醒大家一下)
 

Input

每组输入数据占1行,每行数据的开始是2个整数n(0<=n<=100)和m(0<=m<=100),分别表示集合A和集合B的元素个数,然后紧跟着n+m个元素,前面n个元素属于集合A,其余的属于集合B. 每个元素为不超出int范围的整数,元素之间有一个空格隔开.
如果n=0并且m=0表示输入的结束,不做处理。

Output

针对每组数据输出一行数据,表示A-B的结果,如果结果为空集合,则输出“NULL”,否则从小到大输出结果,为了简化问题,每个元素后面跟一个空格.

sample-input

3 3 1 2 3 1 4 7
3 7 2 5 8 2 3 4 5 6 7 8 
0 0

sample-output

2 3 
NULL

理解

1.在a集合里遍历b中的元素,如果有相同的就剔除,剩下的重新放在集合a中。

2.对a中的元素进行排序即可输出。

AC代码

#include<stdio.h>
int main()
{
	int n,m,i,j,t;
	while((~scanf("%d %d",&n,&m))&&(n!=0||m!=0))
	{
		int a[105],b[105];
		for(i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
		for(j=0;j<m;j++)
		{
			scanf("%d",&b[j]);
		}
		for(j=0;j<m;j++){
			for(i=0;i<n;i++){
				if(a[i]==b[j]){
					n--;
					for(i=i;i<n;i++){
						a[i]=a[i+1];
					}
					break;
				}
			}
		}
		if(n==0){
			printf("NULL");
		}
		else{
			for(i=0;i<n-1;i++){
				for(j=0;j<n-1-i;j++){
					if(a[j]>a[j+1]){
					t=a[j];a[j]=a[j+1];a[j+1]=t;
					}
				}
			}
		for(i=0;i<n;i++){
			printf("%d ",a[i]);
		}
		}
	}
}

D-人见人爱A^B

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”

Input

输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。

Output

对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。

sample-input

2 3
12 6
6789 10000
0 0
 

sample-output

8
984
1
 

理解

1.不能单纯的使用math函数,很用可能在代入较大的数据时出现问题,可以选择循环的方式来实现b个a相乘。

2.再对其向1000取余就可以输出结果了。

AC代码

#include<stdio.h>
#include<math.h>
int main()
{
	long long a,b;
	while((~scanf("%lld %lld",&a,&b))&&(a!=0||b!=0))
	{
		long long c,d;
		c=a;
		for(int i=1;i<b;i++)
		{
			c=c*a;
			c=c%1000;
		}
		printf("%lld",c);
	}
}

(二)牛客周赛round3

A-游游的7的倍数

游游拿到了一个正整数 x,她希望在 x 中添加一个数字,使它成为 7 的倍数。

Input

一个正整数 x(1<=x<=10^9)。

Output

x添加一个数字后形成的数。请务必保证操作的合法性,且一定是7的倍数。如果有多解,输出任意一个合法解。可以证明,至少存在一个正确答案。

Sample Input

1

Sample Output

21

理解

题目没有要求是最小的可以除以7的数,所以可以从n的10倍开始循环10*n+i(0<i<9),当可以除以7时中止然后输出。

AC代码

#include<stdio.h>
int main()
{
    long long x;
    scanf("%lld",&x);
    long long s=0,t;
    if(x==0)
    {
        s=0;
    }
    else
    {
        for(int i=0; ;i++)
        {
            t=i;
            s=x*10+t;
            if(s%7==0)
                break;
        }
    }
    printf("%lld",s);
}

B-游游的字母串

对于一个小写字母而言,游游可以通过一次操作把这个字母变成相邻的字母。'a'和'b'相邻,'b'和'c'相邻,以此类推。特殊的,'a'和'z'也是相邻的。可以认为,小写字母的相邻规则为一个环。

游游拿到了一个仅包含小写字母的字符串,她想知道,使得所有字母都相等至少要多少次操作?

Input

一个仅包含小写字母,长度不超过100000的字符串。

Output

一个整数,代表最小的操作次数。

Sample Input

yab

Sample Output

3

理解

取字符串的长度n,然后循环n次,从a到z遍历,求出第j个字母和相邻的最小距离(0或1),再求和。

AC代码

#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
    char a[100005];
    scanf("%s",&a);
    int n;
    int b=0,c=999999;
    n=strlen(a);
    for(char i='a';i<='z';i++)
    {
        b=0;
        for(int j=0;j<n;j++)
        {
            b=b+fmin(abs((int)a[j]-i),26-abs((int)a[j]-i));
        }
        c=c<b?c:b;
    }
    printf("%d\n",c);
    return 0;
}

C-游游的水果大礼包

游游有nnn个苹果,mmm个桃子。她可以把2个苹果和1个桃子组成价值aaa元的一号水果大礼包,也可以把1个苹果和2个桃子组成价值bbb元的二号水果大礼包。游游想知道,自己最多能组成多少价值总和的大礼包?

Input

四个正整数n,m,a,b,用空格隔开。分别代表苹果的数量、桃子的数量、一号大礼包价值、二号大礼包价值。1<=n,m,a,b<=10^6

Output

一个整数,代表大礼包的最大价值总和。

Sample Input

3 4 1 2

Sample Output

4

理解

先做出a礼包,再判断剩下的材料能做的最多的b礼包,再个数乘以价格,比较求出最大价值。

AC代码

#include<stdio.h>
int main()
{
    long long n,m,a,b;
    scanf("%lld%lld%lld%lld",&n,&m,&a,&b);
    long long s=0,t=0;
    for(int i=0;i<=n/2;i++)
    {
        if(m<i)
            break;
        t=(n-i*2)<((m-i)/2)?(n-i*2):((m-i)/2);
        s=s>(a*i+b*t)?s:(a*i+b*t);
    }
    printf("%lld",s);
}

D-游游的权值矩阵

游游定义一个矩阵权值为:每一对相邻元素之和的总和。
例如,对于矩阵:
1 2
3 4
它的权值是(1+2)+(1+3)+(2+4)+(3+4)=3+4+6+7=20。
游游希望你构造一个n∗nn*nn∗n的矩阵,矩阵中的元素为1到n2n^2n2且每个数恰好出现一次。她希望最终矩阵的权值尽可能大。你能帮帮她吗?由于矩阵可能过大,你不需要输出最终的矩阵,只需要输出这个最大权值即可。答案对109+710^9+7109+7取模。

Input

一个正整数n。
2≤n≤10^9

Output

矩阵的最大权值,对10^9+7取模。

Sample Input

2

Sample Output

20

理解

要求最大的权值则矩阵

1.四个角(只加两次)必须是固定的1,2,3,4

2.除了角的边(加三次)则从5到4*(n-2)-1

3.剩下的即从4*(n-2)到n*n。

AC代码

#include<stdio.h>
const int mod=1e9+7;
long long sum(long long n)
{
    return (n%mod*(n%mod+1)/2)%mod;
}
int main()
{
    long long n,a=0;
    scanf("%lld",&n);
    a=20+((sum(4*(n-2)+4)-sum(4))*3+mod)%mod+(sum(n*n)-sum(4*(n-2)+4)+mod)*4%mod;
    printf("%lld",(a+mod)%mod);
    return 0;
}

(三)知识

(1)用输出中间结果的方法调试

在观察无法找出错误时,可以用“输出中间结果”的方法查错。

while(n>1){
if(n%2==1){
n=n*3+1;
printf("%d",n);
}
else{
n/=2;
printf("%d",n);
}
count++;
}


第一次输出:-13320043321
原因:乘法溢出。

#include<stdio.h>
int main()
{
int n,count=0;
scanf("%d",&n);
while(n>1){
if(n%2==1){
n=3*(n-1)/2+2;
count++;
}
else{
n/=2;
}
count++;
}
printf("%d\n",count);
return0;
}

(2)用重定向的方式读写文件

使用文件最简单的方法是使用输入输出重定向,只需要在main函数的入口处加入
以下两条语句:

freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);

(3)用fopen的方式读写文件

#include<stdio.h>
#defineINF1000000000
intmain(){
FILE*fin,*fout;
fin=fopen("data.in","rb");
fout=fopen("data.out","wb");
intx,n=0,min=INF,max=-INF,s=0;
while(fscanf(fin,"%d",&x)==1){
s+=x;
if(x<min)min=x;
if(x>max)max=x;
n++;
}
fprintf(fout,"%d%d%.3lf\n",min,max,(double)s/n);
fclose(fin);
fclose(fout);
return0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值