半个月总结

半个月总结

写的题:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


递归

递归是一种解决问题的方法,其中一个函数通过不断调用自身来解决规模较小的子问题。递归通常涉及两个部分:基本情况和递归关系。

递归的思想过程:

  1. 基本情况(Base Case): 这是递归函数中最简单、最基础的情况。通常,基本情况是一个问题规模足够小以直接解决的情况,而无需继续递归。
  2. 递归关系(Recursive Relation): 这是递归函数的核心。在递归关系中,问题被分解成规模较小的子问题,并通过递归调用来解决这些子问题。递归关系必须能够使问题逐渐趋于基本情况。
  3. 递归调用: 在递归关系中,函数会调用自身,解决规模较小的子问题。这是递归的关键点。

写递归函数技巧

注意:函数中只需要列出两种情况

1.基本情况

2.找关系式表示n


【深基7.习8】猴子吃桃

题目描述

一只小猴买了若干个桃子。第一天他刚好吃了这些桃子的一半,又贪嘴多吃了一个;接下来的每一天它都会吃剩余的桃子的一半外加一个。第 n n n 天早上起来一看,只剩下 1 1 1 个桃子了。请问小猴买了几个桃子?

输入格式

输入一个正整数 n n n,表示天数。

输出格式

输出小猴买了多少个桃子。

样例 #1

样例输入 #1

4

样例输出 #1

22

提示

数据保证, 1 ≤ n ≤ 20 1\le n\le20 1n20


主要代码:

int amount(int n){
	if(n==1){
		return 1;
	}else{
		return (amount(n-1)+1)*2; //here
	}	
}

P5739 【深基7.例7】计算阶乘

斐波那契数列
int fibonacci(int n) {
    if (n <= 1) {
        return n;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

洛谷


有意思的题

P5739 【深基7.例7】计算阶乘

链接

题目描述

n ! n! n!,也就是 1 × 2 × 3 ⋯ × n 1\times2\times3\dots\times n 1×2×3×n

挑战:尝试不使用循环语句(for、while)完成这个任务。

输入格式

第一行输入一个正整数 n n n

输出格式

输出一个正整数,表示 n ! n! n!

样例 #1

样例输入 #1

3

样例输出 #1

6

提示

数据保证, 1 ≤ n ≤ 12 1 \leq n\le12 1n12


有意思的地方:

挑战:尝试不使用循环语句(for、while)完成这个任务。

那么就有蛮多种解法


递归
#include <stdio.h>
int multiple(int n){
	if(n==0) return 1;
	return n*multiple(n-1);//不断调用函数
}
//n*(n-1)*(n-2)*...*1

int main(){
	int n;
	scanf("%d",&n);
	int sum=multiple(n);
	printf("%d",sum);
    return 0;
}
直接printf
#include <stdio.h>

int main(){
    int a[12]={1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600};
    int n;
    scanf("%d",&n);
    int sum=a[n-1];
    printf("%d",sum);
    return 0;
}
超多个if
include <stdio.h>
    
int main(){
    
    return 0;
}

[USACO1.5] 回文质数 Prime Palindromes

USACO1.5] 回文质数 Prime Palindromes - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

因为 151 151 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 151 151 是回文质数。

写一个程序来找出范围 [ a , b ] ( 5 ≤ a < b ≤ 100 , 000 , 000 ) [a,b] (5 \le a < b \le 100,000,000) [a,b](5a<b100,000,000)(一亿)间的所有回文质数。

输入格式

第一行输入两个正整数 a a a b b b

输出格式

输出一个回文质数的列表,一行一个。

样例 #1

样例输入 #1

5 500

样例输出 #1

5
7
11
101
131
151
181
191
313
353
373
383

提示

Hint 1: Generate the palindromes and see if they are prime.

提示 1: 找出所有的回文数再判断它们是不是质数(素数).

Hint 2: Generate palindromes by combining digits properly. You might need more than one of the loops like below.

提示 2: 要产生正确的回文数,你可能需要几个像下面这样的循环。

题目翻译来自NOCOW。

USACO Training Section 1.5

产生长度为 5 5 5 的回文数:

for (d1 = 1; d1 <= 9; d1+=2) {    // 只有奇数才会是素数
     for (d2 = 0; d2 <= 9; d2++) {
         for (d3 = 0; d3 <= 9; d3++) {
           palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;//(处理回文数...)
         }
     }
 }

分析:

我一开始没看到说明提示这一部分,所以纯按照我自己的理解处理这道题的话

1.写个函数判断是否是素数

2.写个函数判断是否是回文数

3.总和条件判断输出

其中判断是否是回文数相较下来有点动脑(没看提示的话)


一开始自己写的代码:

回文数部分采用数组元素比较处理
先将待处理数每一位存入数组
然后用a[i],a[size-i-1]判断位置对称的两个数是否相等“
但这样写会超时
就当提供了一种思路吧

#include <stdio.h>
#include <math.h>
int a[100000000];

int sushu(int n){
	int i;
	for(i=2;i<=sqrt(n);i++){
		if(n%i==0) return 0;
	}
	return 1;
}


int huiwen(int n){
	int i=0;
	while(n!=0){
		a[i++]=n%10;
		n/=10;
	}
	int size=i;
	for(i=0;i<size/2;i++){
		if(a[i]!=a[size-i-1]) return 0;
	}
	return 1;
}

int main(){
	int a,b;
	scanf("%d %d",&a,&b);
	int i;
	for(i=a;i<=b;i++){
		if(huiwen(i)&&sushu(i)) printf("%d\n",i);
	}
	return 0;
} 

AC代码:

就照做提示部分就好
将数倒置然后再和原来的数比较

#include <stdio.h>
#include <math.h>


int sushu(int n){
	int i;
	for(i=2;i<=sqrt(n);i++){
		if(n%i==0) return 0;
	}
	return 1;
}

int is_palindrome(int n) {
    int reversed = 0, original = n;

    while (n > 0) {
        reversed = reversed * 10 + (n % 10);
        n /= 10;
    }

    return (original == reversed);
}

int main() {
    int a, b;
    scanf("%d %d", &a, &b);

    for (int i = a; i <= b; i++) {
        if (is_palindrome(i) && sushu(i)) {
            printf("%d\n", i);
        }
    }
    return 0;
}

赦免战俘

P5461 赦免战俘 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目背景

借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!

题目描述

现有 2 n × 2 n ( n ≤ 10 ) 2^n\times 2^n (n\le10) 2n×2n(n10) 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵,每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免,剩下 3 个小矩阵中,每一个矩阵继续分为 4 个更小的矩阵,然后通过同样的方式赦免作弊者……直到矩阵无法再分下去为止。所有没有被赦免的作弊者都将被处以棕名处罚。

给出 n n n,请输出每名作弊者的命运,其中 0 代表被赦免,1 代表不被赦免。

输入格式

一个整数 n n n

输出格式

2 n × 2 n 2^n \times 2^n 2n×2n 的 01 矩阵,代表每个人是否被赦免。数字之间有一个空格。

样例 #1

样例输入 #1

3

样例输出 #1

0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 1
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 1
0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1

分析:

这道题的意思就是将一个二维数组切成四块,左上那一块全部赋值为0,然后将四块每一块继续切四块,左上继续赋值为0

从这就能看出要用到递归

最最最主要就是找到每一次的左上部分

然后利用递归不断切分
直至切分部分只剩下一个数

注意:

为了方便赋值,先将二维数组全赋值为0
左上部分需要变为0的先处理为1
方便写代码


代码:
#include <stdio.h>
#include <math.h>
#define N 2005 //定义的大一些,定义2的10次方会越界 
int n;
int a[N][N]={0};

void Dfs(int x,int y,int xx,int yy){
	if(x==xx||y==yy) return;
	int tx=(x+xx)/2,ty=(y+yy)/2;
	int i,j;
	for(i=x;i<=tx;i++){
		for(j=y;j<=ty;j++){
			a[i][j]=1; //先找到将要变为0的元素,赋值为1
		}
	}
	Dfs(x,ty+1,tx,yy);
	Dfs(tx+1,y,xx,ty);
	Dfs(tx+1,ty+1,xx,yy); //继续切分
}

int main(){
	int x;
	scanf("%d",&x);
	n=pow(2,x);
	Dfs(1,1,n,n);
	int i,j;
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			printf("%d%c",a[i][j]?0:1,j==n?'\n':' ');
		}
	}
	return 0;
}

统计方形(数据加强版)

题目背景

1997年普及组第一题

题目描述

有一个 n × m n \times m n×m 方格的棋盘,求其方格包含多少正方形、长方形(不包含正方形)。

输入格式

一行,两个正整数 n , m n,m n,m n ≤ 5000 , m ≤ 5000 n \leq 5000,m \leq 5000 n5000,m5000)。*

输出格式

一行,两个正整数,分别表示方格包含多少正方形、长方形(不包含正方形)。

样例 #1

样例输入 #1

2 3

样例输出 #1

8 10

大佬的思考过程 P2241 统计方形(数据加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

更细致的过程

代码:

#include<stdio.h>

int main() {
    int n, m, rec = 0, sqr = 0;
    scanf("%d %d", &n, &m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (i == j)
                sqr += (n - i) * (m - j);
            else
                rec += (n - i) * (m - j);
        }
    }
    printf("%d %d\n", sqr, rec);
    return 0;
}

集合求和

题目描述

给定一个集合 s s s(集合元素数量 ≤ 30 \le 30 30),求出此集合所有子集元素之和。

输入格式

集合中的元素(元素 ≤ 1000 \le 1000 1000

输出格式

s s s 所有子集元素之和。

样例 #1

样例输入 #1

2 3

样例输出 #1

10

提示

【样例解释】

子集为: ∅ , { 2 } , { 3 } , { 2 , 3 } \varnothing, \{ 2 \}, \{ 3 \}, \{ 2, 3 \} ,{2},{3},{2,3},和为 2 + 3 + 2 + 3 = 10 2 + 3 + 2 + 3 = 10 2+3+2+3=10


【数据范围】

对于 100 % 100 \% 100% 的数据, 1 ≤ ∣ s ∣ ≤ 30 1 \le \lvert s \rvert \le 30 1s30 1 ≤ s i ≤ 1000 1 \le s_i \le 1000 1si1000 s s s 所有子集元素之和 ≤ 10 18 \le {10}^{18} 1018


注意数据类型为long long

分析过程:在这里插入图片描述

代码:

#include <stdio.h>
#include <math.h>

#define N 100010
long long a[N];
long long sum=0;
long long total=0;

int main() {
	int i = 0;
	int cnt=0;
    while (scanf("%lld", &a[++cnt]) == 1);


    for (i = 1; i < cnt; i++) {
        sum += a[i];
    }

    long long num = (long long)pow(2,cnt-2);
    long long total = sum * num;
    printf("%lld\n", total);

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JaneHan_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值