牛客竞赛-新手上路-语法入门-数组字符串 .c

本文介绍了多个编程算法题目,涉及序列处理、数学计算和逻辑判断。包括随机序列的极差与方差计算、数字出现次数统计、约瑟夫环问题、逆序数求解、课程满意度计算、有序序列合并等。每个题目通过示例代码展示了具体的解决方案,如使用循环、递归、数组操作等方法。

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

1001 随机序列

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

国中生Chino总是做不完数学作业,Cocoa想来帮忙,但作业太多了,怎么也做不完。

Chino的数学作业由T(1≤T≤100)T(1\leq T\leq 100)T(1≤T≤100)张试卷组成,每张试卷上有n(1≤n≤103)n(1\leq n\leq 10^3)n(1≤n≤103)个数a1..n(1≤a≤5000)a_{1..n}(1\leq a\leq 5000)a1..n​(1≤a≤5000),Chino需要算出这些数的极差和方差。极差是一个整数,方差是一个浮点数,要求保留到小数点后3位。

虽然题目很简单,但计算量对于Chino来说实在太大啦!你能帮一帮她吗?

P.S.:一个数列的极差是指数列中最大的数减去最小的数,方差是指算出数列中每个数与数列平均值之差的平方后,对其求和,再除以数列元素个数得到的结果。

输入描述:

 

输入的第一行有一个数T,表示试卷的数量;接下来的每2行,第一行有一个数n,表示当前试卷上数字的个数;第二行有n个数字aia_iai​,表示这张试卷上的每一个数。

输出描述:

对每张试卷,输出一行两个数,分别表示这些数字的极差和方差,中间用空格分开。其中极差是整数,方差是保留到小数点后3位的浮点数。

代码:

#include<stdio.h>
#include<math.h>
int main()
{
    int t,n,a[5000];
    int i=0,j,jicha,max,min,sum;
    double fangcha,aver;
    scanf("%d",&t);
    for(i=0;i<t;i++)
    {
        scanf("%d",&n);
        sum=0;
        fangcha=0;
        jicha=0;
//以上三个变量每次循环前记得归零
        for(j=0;j<n;j++)
        {
            scanf("%d",&a[j]);
            sum+=a[j];
        }
        max=min=a[0];
        aver=1.0/n*sum;
        for(j=0;j<n;j++)
        {
            if(a[j]>max) max=a[j];
            if(a[j]<min) min=a[j];
            fangcha+=pow(a[j]-aver,2);//方差
        }
        jicha=max-min;//极差
        printf("%d %.3f\n",jicha,fangcha/n);
    }
    return 0;
}

思路: 

利用输入和循环的配合,来保证输入数据个数正确。每次循环后输出当前的结果,之后进行下一轮循环中的输入。

思路: 

1002 [NOIP2013]记数问题

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

试计算在区间1 到n 的所有整数中,数字x(0 ≤ x ≤ 9)共出现了多少次?

例如,在1到11 中,即在1、2、3、4、5、6、7、8、9、10、11 中,数字1 出现了4 次。

输入描述:

输入共1行,包含2个整数n、x,之间用一个空格隔开。

输出描述:

输出共1行,包含一个整数,表示x出现的次数。

代码:

#include <stdio.h> 
int main ()
{
	int i,j,a,t=0,n;
	scanf("%d %d",&n,&a);
	for(i=1;i<=n;i++)
//一个循环,依次判断当前数字i,是否是指定数字a
	{
		for(j=i;j;j/=10)
//判断条件为j,当j被除至商为0时停止
//此时刚好判断完i所有位数是否含指定数字a
		{
			if(j%10==a)
			t++;
		}	
	}
	printf("%d",t);
	return 0;
}

 

 思路:

1. 当前代码思路:

思路较为简单,从1到n依次判断每个数中含有几个a,累加起来。

2. 刚开始的个人思路:

起初感觉一个一个循环,判断,计数太过耗时,于是为避免一个一个数去判断和计数,尝试用分析规律,直接计算的方式来编,降低时间复杂度。分析n的每一位上的数与指定数字a的大小关系,直接计算从1到n的n个数中,个位、十位、百位...出现a的次数——结果编不出来,测试用例连一半都没过,自己实在分析不出来,于是我屈服了,屈服给了嵌套循环。

后续:用这个思路ac了,运行时间也降下来了!

代码:

#include <stdio.h> 
int main ()
{
	int i,j,a,ans=0,n;
	scanf("%d %d",&n,&a);
	for(i=1;n/i;i*=10)
    {
        if(a==0)
//a==0情况特殊单独讨论
        {
            if(n/i<10) break;
//a==0时,最大位上的数不能参与计算
//且最高位不可能为0
            if((n/i)%10>a)
//当 当前位上的数 大于a(也就是0)时
//同一般情况下的 ((n/i)%10<a)
//因为是从1开始的计数,而不是从0开始的
//所以才是和 ((n/i)%10<a)情况相同
//而不是 ((n/i)%10>a)的情况
                ans+=(n/i/10)*i;
/*
以255为例
个位是0的情况:10 20 ... 
              100(只会计算个位的0的个数,所以不必担心十位上的0是否会漏掉)
              ... 200 ... 250   共25个
        符合表达式:n/10
十位是0的情况:100 101 102 ... 109 200 201 ... 209 共20个
        符合表达式:n/100*10
测试多组类似数据后,
于是可以发现规律:(n/i/10)*i;
*/
            else
//当 当前位上的数 等于a(也就是0)时
//此情况与一般情况的 当前位的数【(n/i)%10==a】不一样
                ans+=n-(n/i*i-1)+((n/i-1)/10)*i;
/*
以207为例
个位是0:10 20 ... 200 共20个
    不够特殊,下一位
十位是0:100 101 ... 109 200 201 ... 207 共18位
    很明显不可以与【a==0&&(n/i)%10>a】的情况共用同一表达式
    所以才有对本情况的讨论
    经过多组数据的测试
    最终才得出一个表达式:
    n-(n/i*i-1)+((n/i-1)/10)*i
    (其实这个表达式的具体意义我也不算很清楚,毕竟是试出来的)
*/
        }
        else
//一般情况的讨论与分析过程类似a==0的情况,不再一一赘述了(其实是讲不清)
        {
            if((n/i)%10<a)
                ans+=(n/i/10)*i;
            else if((n/i)%10>a)
                ans+=(n/i/10+1)*i;
            else ans+=n-(n/i*i-1)+(n/i/10)*i;
        }
    }
	printf("%d",ans);
	return 0;
}

 

运行时间直接降到个位数!!! 嘴角疯狂上扬!

咳咳,毕竟第一次,多少得意一点应该没事吧(小声)

本代码通过和原本已经ac的(思路1的)代码进行对比,分析各种情况的输入下的输出差异,来进行调试,毕竟题目公布出来的测试用例只有一组,很难分析代码为什么没有通过,自己是漏掉了哪种情况。

自己列测试用例要考虑的情况:

  • 一般情况(a!=0)
    • 某一位上的数大于指定数a
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值