【15.10.30考试】考试分析

本文分析了竞赛课的首次考试,包括货物互通、颠簸的旅程及电话节三道题目,详细介绍了每道题目的解题思路、注意事项及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上竞赛课以来第一次考试,谜之运气爆棚。

总之因为犯了一些死蠢的错误,来写个考试分析。

第一题

货物互通(goods)  
【题目描述】 在银河系中有好多有着高等生物的类地球星球,α星球和β星球就是其中的两个,这两个星球每年都
会派出大使互通货物,α大使和β大使会先带着货物都到达位于中间的γ星球交换货物,如果α大使带的 货物更值钱,β大使需要再付相差的β币,如果β大使带的货物更值钱的话,α大使需要再付相差的α币。 请帮助α大使和β大使计算出,需要付的相差的币值,如果货物等价则输出 0。  
【输入】 输入三行,第一行有两个整数:α星球的货币进制 A和β星球的货币进制 B(2 <= A,B <= 16) 第二行为α大使所带货物的价值(α进制数) 第三行为β大使所带货物的价值(β进制数)  
【输出】 输出为一行,需要付给对方的相差(α或β)币值。

【数据范围】 对于 100%数据,2 <= A,B <= 16,αβ星球的货物价值不超过 10 进制 long long 范围。 


 总之看完题就知道,这是一道会让人写的十分闹心的进制转换。

大概需要注意的点有以下几个

1.因为有十进制以上的进制,所以要注意字符与数字之间的转换

这一项我预处理了两个数组c2n和n2c。

2.注意数据范围是不超过十进制的long long范围,那么转换成最长的 或者说是二进制数 最多会有64位,所以存数的时候至少要开一个长度为64的数组

我差点就被这儿坑了……一开始写的数组大小只有40,还是我后来写完了随便给自己出了一组数据发现数组越界才发现的=-=|||果然数据范围最坑人【明明是你不仔细看题

3.如果是a的货物比b多的话,多付的钱用b进制表示,反之用a进制表示。

第一次写的时候就写反了……输入样例发现咋有那么多f,才知道写错了orz


我的代码如下

#include<stdio.h>
#include<string.h>
long long b10=0,a10=0;
char aho[70];
char bho[70];
int ans[70];
int c2n[255];
char n2c[255];
long long quana[65];
long long quanb[65];
int zhuan(int k,long long x)
{
	int cnt = 0;
	do
	{
		ans[cnt]= x%k;
		x = x/k;
		cnt++;
	}while(x>0);
	return cnt;
}
int main()
{
	for(int i = 'A';i<= 'F';i++)
	{
		c2n[i] = i-'A'+10;
		n2c[i-'A'+10] = i;
	}
	for(int i ='0';i<='9';i++)
	{
		c2n[i] = i-'0';
		n2c[i-'0'] = i;
	}
	int a,b;
	scanf("%d%d",&a,&b);
	quana[0]=1;
	quanb[0]=1;
	for(int i = 1;i<=64;i++)
	{
		quana[i]=quana[i-1]*a;
		quanb[i]=quanb[i-1]*b;
	}
	scanf("%s",aho);
	scanf("%s",bho);
	for(int i = 0;i<strlen(aho);i++)
	{
		a10+=c2n[aho[i]]*quana[strlen(aho)-1-i];
	}
	for(int i = 0;i<strlen(bho);i++)
	{
		b10+=c2n[bho[i]]*quanb[strlen(bho)-1-i];
	}
	if(a10==b10)
	{
		printf("0");
	}
	else if(a10>b10)
	{
		int cnt = zhuan(b,a10-b10);
		for(int i = cnt-1;i>=0;i--)
		{
			printf("%c",n2c[ans[i]]);
		}
	}else if(a10<b10)
	{
		int cnt = zhuan(a,b10-a10);
		for(int i = cnt-1;i>=0;i--)
		{
			printf("%c",n2c[ans[i]]);
		}
	}
	return 0;
}


现在看来真是一坨莫名其妙的代码…尤其是看了标程之后【手动打脸表情



第二题


颠簸的旅程(bump)  
【题目描述】 交易完成后α大使准备返回α星球的时候,发现飞船有故障,每当仪 表里程盘里面的数字更新时,如果里面包含数字 x,飞船就会颠簸,里面有 几个 x 就会颠簸几下,出发前仪表盘的里程数是 S,到α星球的距离是 L, 请帮忙求出整个返回过程中,到达α星球时,飞船一共会颠簸多少下。  
【输入】 输入为一行,三个整数,依次是初始里程数 S,距离 L,会产生颠簸的数字 x。  
【输出】 输出为一行一个整数,飞船总共颠簸的次数。 
【数据范围】 对于 100%数据,0 <= S,L <= 106,0 <= x <= 9。 


数位分割求某个数字出现的次数,很简单的题,老师还贴心的给出了样例解释,于是我绕过了唯一一个坑。

坑:数字是从开始变化的开始颠,初始数值不算,所以循环其实是从初始里程值+1开始的。


于是我的代码如下

#include<stdio.h>
int dian;
int judge(int x)
{
	int cnt = 0;
	do
	{
		if(x%10==dian)
		{
			cnt++;
		}
		x/=10;
	}while(x>0);
	return cnt;
}
int main()
{
	int start,length,ans = 0;
	scanf("%d%d%d",&start,&length,&dian);
	for(int i = start+1;i<= start+length;i++)
	{
		ans+=judge(i);
	}
	printf("%d",ans);
	return 0;
}


这里要说一下,函数里写do while是因为本来没注意到那个坑,以为可能从0开始……

后来发现了坑,于是不可能从0开始了……但也懒得改了……毕竟这么写也没啥错【摊手


第三题


电话节(telephone)  
【题目描述】 α大使历尽颠簸千辛,终于回到了α星球,正好赶上了α星球最盛大的节日:电话节。α星球共有 N 户人家,每户人家都有一个威望值 ai,在电话节的时候,每户人家都要给其他所有人打电话,通话时间就 是两家威望的乘积,请帮忙算一下,一个电话节下来,α星球总共会产生多少通话时间,答案可能会很大, 最终答案 mod 10009 即可。  
【输入】 第一行一个数字 N,表示α星球共有 N 户人家。 第二行有 N 个整数,表示α星球每户人家的威望 ai。  
【输出】 输出一个整数,最终答案 mod 10009 的结果。 

【数据范围】 对于 20%的数据,1 <= N <= 100,0 <= ai <= 100。 对于 50%的数据,1 <= N <= 1000。 对于 100%的数据,1 <= N <= 106,0 <= ai <= 1000。  
【样例解释】 a1和 a2通话时间是 6, a1和 a3通话时间是 8, a2和 a1通话时间是 6, a2和a3通话时间是12, a3和 a1通话时间是 8, a3和a2通话时间是12, 总通话时间为 6 + 8 + 6 + 12 + 8 + 12 = 52。 


依旧是良心样例解释系列……我一开始根本没懂样例为啥得52……

经过分析后可知,第ai家要给除ai的其他所有人打电话,于是ai家的通话时间就为

ai = ai*a1+ai*a2*………………+ai*an;

于是整理得ai= ai*(a1+a2+……a(i-1)+a(i+1)……+an)

同时可预先将a1~an加和为sum

则ai = ai*(sum-ai);


这道题最神的是我一开始莫名算错数据范围用了个快速乘……于是时间复杂度升高……但这还不是重点 重点是我当场居然踩着线拿了满点orz

当然后来测就是最后两个点超时了……不过把快速乘去掉之后就好了……

考试的时候一定是有幸运之神附体了orz

这道题需要注意的还有要在过程中一直mod10009,不然也会瞬间爆炸【X

总之去掉了快速乘的代码如下……

#include<stdio.h>
int mod = 10009;
int weiwang[1000005];
int main()
{
	long long sum = 0;
	int n;
	scanf("%d",&n);
	for(int i = 1;i<= n;i++)
	{
		scanf("%d",&weiwang[i]);
		sum +=weiwang[i];
	}
	long long ans = 0;
	for(int i = 1;i<= n;i++)
	{
		ans=(ans+weiwang[i]*(sum-weiwang[i]))%mod;
	}
	printf("%I64d",ans);
	return 0;
}


以上……就是竞赛课开始之后的第一次考试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值