月末考核复习 周任务一

总结:字典序全排列  高精度加法  二分法(没做) 前缀和   开始热身了 不是很难 但第一次接触算法 不免的走了很多弯路

周任务一

一、抽签(字典序全排列)

智能组在比赛的时候,经常通过抽签的形式来决定上场的顺序,Cherry想让你帮忙看看,如果有n支队伍参赛,会有多少种情况以及上场顺序的字典序全排列。

例如:如果有3支队伍,就有6种情况

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

输入

第一行输入一个N,表示有多少个队伍

样例输入 
4
输出

输出全排列,每个字之间有一个空格,每输出一组有一个换行。 

注意:最后一行也有回车

样例输出 
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1

代码实现 

#include<stdio.h>
//右移函数
void swapleft(int* arr, int a, int b) {
	int temp = arr[b];
	for (int i = b; i >= a + 1; i--) {
		arr[i] = arr[i - 1];
	}
	arr[a] = temp;
}
//
//左移函数
void swapright(int* arr, int a, int b) {
	int temp = arr[a];
	for (int i = a; i <= b - 1; i++) {
		arr[i] = arr[i + 1];
	}
	arr[b] = temp;
}

//字典序全排列
void perm(int n, int* a, int p, int q) {
	if (p == q) {
		for (int i = 0; i < n; i++) {
			printf("%d ", a[i]);
		}
		putchar('\n');
	}
	else {
		for (int i = p; i <= q; i++) {
			swapleft(a, p, i);
			perm(n, a, p + 1, q);
			swapright(a, p, i);
		}
	}
}
//
int main()
{
	int n;
	scanf("%d", &n);

	int i;
	int a[100];
	for (i = 0; i < n; i++) {
		a[i] = i + 1;
	}

	perm(n, a, 0, n - 1);

	return 0;
}

经验总结

递归 字典序全排列

递归还是烧脑壳

二、小学生计算题(高精度加法

mkk学长给大家出了一道小学生都会的简单计算题,问题是这样的,给出了A,B两个正整数,现在对他们进行简单加法,运算格式是:“(A + B)”,现在请你运算出结果。

输入

两个正整数0 <= A,B <= 10000000000000000000000000000000

样例输入 
1 1
输出

一个正整数

样例输出 
2

代码实现 

#include<string.h>
//准备
#define LEN 1004
int a[LEN], b[LEN], c[LEN], d[LEN], rm[LEN], ra[LEN], rs[LEN];
void clear(int a[]) {
	for (int i = 0; i < LEN; ++i)
		a[i] = 0;
}

void read(int a[]) {
	char s[LEN + 1];
	scanf("%s", s);

	clear(a);

	int len = strlen(s);
	for (int i = 0; i < len; ++i)
		a[len - i - 1] = s[i] - '0';
}

void print(int a[]) {
	int i;
	for (i = LEN - 1; i >= 1; --i)
		if (a[i] != 0)
			break;
	for (; i >= 0; --i)
		putchar(a[i] + '0');
	putchar('\n');
}
//
//加法
void add(int a[], int b[], int c[]) {
	clear(c);

	for (int i = 0; i < LEN - 1; ++i) {
		c[i] += a[i] + b[i];
		if (c[i] >= 10) {
			c[i + 1] += 1;
			c[i] -= 10;
		}
	}
}

经验总结

高精度加法

从OI wiki上重新学的一套 自己手搓的又难又懒又烂

三、杨辉三角(算没做出来吧 时间到了没写完后面也没写了)

杨辉三角形是我们所熟悉的数学模型,如果我们把杨辉三角按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,…1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,… 

现给定一个正整数N,请你输出在上述数列中第一次出现 N 时,N是第几个数。

输入

一个正整数N,1<=N<=1e9

样例输入 
6
输出

一个正整数

样例输出 
13

四、拿元器件(前缀和)

工作室买了n个盒子(每个盒子的容量无限大),将它们从1∼n 编号,并且最开始i号盒子中装有Ai个元器件。现在你最多可以进行 k 次操作,每次操作只能选择一个编号为x的盒子(1<=x<=n-1),然后把x号盒子中的元器件全部放到x+1号盒子中。 

最后你可以任意选择一个盒子,问,你最多能拿到多少个元器件。

输入

第一行有两个非负整数n,k(n与k之间用空格隔开),n表示盒子的个数,k表示操作次数上限。 

第二行有n个非负整数,相邻两个数用空格隔开,表示盒子中的最开始装的元器件个数A1, A2, ⋯, An。

样例输入 
10 5
890 965 256 419 296 987 45 676 976 742
输出

一行,仅一个非负整数,表示所能拿到的最多元器件。

样例输出 
3813

代码实现 

#include <stdlib.h>
#include<string.h>
#define getm(type,len) (type*)malloc(sizeof(type)*len)//动态创建数组 好用 c++可以用new更好用
int main()
{
	int n, k;
	scanf("%d%d", &n, &k);
	getchar();

	int* a = getm(int, n);
	memset(a, 0, sizeof(int) * n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &a[i]);
	}

	int* sum = getm(int, n);//计算前缀和
	for (int i = 0; i <= n; i++) {
		if (i == 0) {
			sum[i] = a[i];
		}
		else
			sum[i] = sum[i - 1] + a[i];
	}

	int max = 0;
	int temp = 0;
	int i;
	for (i = 0; i < n; i++)//遍历前缀和
 {
		if (i <= k)//若小于操作次数
 {
			temp = sum[i];
		}
		else {
			temp = sum[i] - sum[i - k - 1];

		}

		if (max < temp)
			max = temp;
	}
	printf("%d", max);

	return 0;
}

经验总结 

前缀和

一定要理清加减时的逻辑关系 如这题k为操作次数 遍历时i为位置 不能简单相等 不然就像做这道题一样花大量时间调试最后的拆分 得到虽然正确但不简洁不易理解的逻辑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值