- 错过比赛的同学请点进每道题的**原题链接**补题
------------
###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 人评分