c语言验证某范围尼克切斯,hevttc暑期训练2 - 题解

本文介绍了编程中常见的数列求和问题及其解决方案,包括斐波那契数列变形的求和、自由下落距离计算、字符串排序、数列去重、特定数的位数和计算、尼克切斯定理验证以及哥德巴赫猜想的程序实现。通过这些实例展示了C语言在算法问题上的应用和优化技巧。
摘要由CSDN通过智能技术生成

- 错过比赛的同学请点进每道题的**原题链接**补题

------------

###A.有规律的数列求和

原题链接:[有规律的数列求和](https://www.dotcpp.com/oj/problem1018.html "有规律的数列求和")

实现数列$$\frac{2}{1}+\frac{3}{2}+\frac{5}{3}+\frac{8}{5}+\frac{13}{8}+$$……的前$$n$$项和

我们不难发现,这个数列实际上是**斐波那契数列**的变形

但是为了方便做实数除法,我们把分子、分母都定义成$$double$$类型

(设a为较大的斐波那契数)

在进行**斐波那契数列**的迭代时,我们可以利用中间变量实现

```

t = a + b;

b = a;

a = t;

```

------------

我们也可以利用一种巧妙的方法,不用中间变量同样可以实现数列的迭代

```

a = a + b;

b = a - b;

```

大家只要自己模拟一下,就能发现它确实可以实现这样的功能

然后累加$$n$$次$$a/b$$,输出结果

------------

#####C语言代码

```

#includeint main()

{

int n;

double a = 2, b = 1, sum = 0;

scanf("%d", &n);

for(int i = 0; i < n; i ++)

{

sum += a / b;

a = a + b;

b = a - b;

}

printf("%.2lf", sum);

return 0;

}

```

------------

###B.自由下落的距离计算

原题链接:[自由下落的距离计算](https://www.dotcpp.com/oj/problem1019.html "自由下落的距离计算")

####利用一些性质,我们可以在O(1)的时间复杂度内得到结果

初始高度为$$m$$,由于每次弹起的高度是上次的一半

所以最后一次弹起的高度为 $$\frac{m}{2^n}$$

利用位运算`1 << n`求出$$2^n$$

变量$$h$$和$$m$$本身是double类型,所以直接做除法运算

`h = m / (1 << n) `

------------

从第一次弹起再落地算起

每次落地弹起落地经过的高度是公比为$$\frac{1}{2}$$的等比数列

初次弹起高度为$$\frac{m}{2}$$,弹起落地总和为$$m$$,记$$a_1=m$$

最后一次弹起高度为$$h$$,弹起落地总和为$$2h$$,记$$a_n=2h$$

#####利用等比数列求和公式

$$Sn=\frac{a_1-a_n\cdot q}{1-q}$$

再加上初始高度$$m$$,得出第$$n$$次落地时总共经过的高度

`ans = m + (m - h * 2) * 2`

------------

#####C语言代码

```

#includeint main()

{

double m, h, ans;

int n;

scanf("%lf%d",&m,&n);

h = m / (1 << n);

ans = m + (m - h * 2) * 2;

printf("%.2lf %.2lf", h, ans);

return 0;

}

```

------------

###C.三个字符串的排序

原题链接:[三个字符串的排序](https://www.dotcpp.com/oj/problem1044.html "三个字符串的排序")

虽然只是三个字符串,但是全排列有$$3!=6$$种情况,写起来非常复杂

所以我们不考虑三个字符串的排列,而考虑$$n$$个字符串的排列

用简单的选择排序就可以

数之间的比较大小用关系运算符,字符串就用函数`strcmp()`

数之间交换可以利用中间变量,字符串也同样可以,赋值从等号改成`strcpy`

#####C语言代码

```

#include#includeint main()

{

const int n = 3;

char a[3][1024], t[1024];

for(int i = 0; i < n; i ++) gets(a[i]);

for(int i = 0; i < n - 1; i ++)

for(int j = i + 1; j < n; j ++)

if(strcmp(a[i], a[j]) > 0)

{

strcpy(t, a[i]);

strcpy(a[i], a[j]);

strcpy(a[j], t);

}

for(int i = 0; i < n; i ++) puts(a[i]);

return 0;

}

```

------------

###D.明明的随机数

原题链接:[明明的随机数](https://www.dotcpp.com/oj/problem1102.html "明明的随机数")

数列排序去重,方法很多,介绍一种选择排序的同时去重的方法

去重时总元素个数-1,让后面的元素覆盖掉a[j]

注意也要同时让j--,因为此时的a[j]已经是新的没有和a[i]比较过的元素,需要重新判断

```

#includeint main()

{

int n, a[1024];

scanf("%d", &n);

for(int i = 0; i < n; i ++) scanf("%d", &a[i]);

for(int i = 0; i < n - 1; i ++)

for(int j = i + 1; j < n; j ++)

if(a[i] > a[j])

{

int t = a[i];

a[i] = a[j];

a[j] = t;

}else if(a[i] == a[j]){

n --;

for(int k = j; k < n; k ++) a[k] = a[k + 1];

j --;

}

printf("%d\n", n);

for(int i = 0; i < n; i ++) printf("%d ", a[i]);

return 0;

}

```

------------

###E.Tom数

原题链接:[Tom数](https://www.dotcpp.com/oj/problem1118.html "Tom数")

统计数的各位数字之和,需要注意的就是$$n<2^{32}$$超过整型范围需要用long long

未知组输入数据可以利用scanf的返回值判断是否有新数据读入

```

#includeint main()

{

long long n;

while(~scanf("%lld", &n))

{

int ans = 0;

while(n)

{

ans += n % 10;

n /= 10;

}

printf("%d\n", ans);

}

return 0;

}

```

------------

###F.尼科彻斯定理

原题链接:[尼克切斯定理](https://www.dotcpp.com/oj/problem1127.html "尼克切斯定理")

没啥好说的,算出$$m^3$$和开头的奇数,然后按照格式输出

```

#includeint main()

{

int m, n;

scanf("%d",&m);

int m3 = m * m * m;

n = m3 / m - m + 1;

printf("%d*%d*%d=%d=", m, m, m, m3);

for(int i = 0; i < m; i ++)

{

printf("%d+", n);

n += 2;

}

printf("%d\n", n);

return 0;

}

```

------------

###G.哥德巴赫曾猜测

原题链接:[哥德巴赫猜想](https://www.dotcpp.com/oj/problem1199.html "哥德巴赫猜想")

循环从$$2$$开始遍历到$$n/2$$,判断$$i$$与$$n-i$$是否同时为素数

如果满足条件,那么计数器自增

```

#includeint isprime(int n)

{

for(int i = 2; i * i <= n; i ++)

if(n % i == 0) return 0;

return 1;

}

int main()

{

int n, count = 0;

scanf("%d", &n);

for(int i = 2; i <= n / 2; i ++)

if(isprime(i) && isprime(n - i)) count ++;

printf("%d", count);

return 0;

}

```

0.0分

2 人评分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值