总结:字典序全排列 高精度加法 二分法(没做) 前缀和 开始热身了 不是很难 但第一次接触算法 不免的走了很多弯路
周任务一
一、抽签(字典序全排列)
智能组在比赛的时候,经常通过抽签的形式来决定上场的顺序,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为位置 不能简单相等 不然就像做这道题一样花大量时间调试最后的拆分 得到虽然正确但不简洁不易理解的逻辑