#include <iostream>
using namespace std;
int main()
{
int sum = 0, res = 0; // 每一层的总数,和全部层的总数
for (int i = 1; i <= 100; ++i)
{
sum += i;
res += sum;
}
cout << res << endl;
return 0;
}
#include <iostream>
using namespace std;
int main()
{
for (int i = 1; i <= 100; ++i)
{
int res = 0; // 总计吹的总数
for (int j = i; j <= 100; ++j) // 从第几岁开始过生日
{
res += j;
if (res == 236)
cout << i << endl; // 答案26
}
}
return 0;
}
3C:凑算式(11分填空_全排列)
题目描述:
cpp复制代码
B DEF
A + --- + --------- = 10
C GHI
题目解析:
暴力循环,直接用next_permutation()。答案29
cpp复制代码
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int num[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int cnt = 0;
do
{
float a = num[0];
float b = num[1] * 1.0 / num[2];
float c = (num[3] * 100.0 + num[4] * 10 + num[5]) / (num[6] * 100 + num[7] * 10 + num[8]);
if (fabs(a + b + c - 10) <= 1e-5)
{
cnt++;
}
} while (next_permutation(num, num + 9));
cout << cnt << endl; // 答案29
return 0;
}
4D:快速排序(9分代码填空)
题目描述:
排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先选一个"标尺",
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。
下面的代码是一种实现,请分析并填写划线部分缺少的代码。
cpp复制代码
#include <stdio.h>
void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
int partition(int a[], int p, int r)
{
int i = p;
int j = r + 1;
int x = a[p];
while(1)
{
while(i<r && a[++i]<x);
while(a[--j]>x);
if(i>=j) break;
swap(a,i,j);
}
______________________;//填空
return j;
}
void quicksort(int a[], int p, int r)
{
if(p<r)
{
int q = partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
int main()
{
int i;
int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
int N = 12;
quicksort(a, 0, N-1);
for(i=0; i<N; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
#include <algorithm>
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
int a[12] = { 0,0,0,0,0,0,0,1,1,1,1,1 };
void dfs(vector<vector<int>>& m, int i, int j) {
m[i][j] = 0;
if (i - 1 >= 0 && m[i - 1][j] == 1) // 四个方向
dfs(m, i - 1, j);
if (i + 1 <= 2 && m[i + 1][j] == 1)
dfs(m, i + 1, j);
if (j - 1 >= 0 && m[i][j - 1] == 1)
dfs(m, i, j - 1);
if (j + 1 <= 3 && m[i][j + 1] == 1)
dfs(m, i, j + 1);
}
bool check(int arr[])
{
vector<vector<int>> map(3, vector<int>(4)); // 生成a对应的二维矩阵
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++){
map[i][j] = arr[i * 4 + j] == 1 ? 1 : 0;
}
}
// 连通性检测,如果连通块的数量为1,则是一种正确的方案
int count = 0; // 连通块的数量
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
if (map[i][j] == 1)
{
dfs(map, i, j);
count++;
}
}
}
return count == 1;
}
int main()
{
int ans = 0; // 用a数组产生全排列代表选择5个位置的邮票
do
{
if (check(a))
{
ans++;
}
} while (next_permutation(a, a + 12));//全排列函数
cout << ans << endl;
//cout << clock() << "ms" << endl;//看看跑了多长时间
return 0;
}
代码2:
cpp复制代码
#include<iostream>
using namespace std;
const int N = 15;
int ans;
int p[N];
int e[N][N];
bool used[N];
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
void dfs(int u, int start)
{
if (u == 5)
{
for (int i = 1; i <= 12; ++i)
{
p[i] = i;
}
for (int i = 1; i <= 12; ++i)
{
for (int j = 1; j <= 12; ++j)
{
if (e[i][j] && used[i] && used[j])
{
p[find(i)] = find(j);
}
}
}
int cnt = 0;
for (int i = 1; i <= 12; ++i)
{
if (used[i] && p[i] == i)
{
cnt++;
}
}
if (cnt == 1)
++ans;
return;
}
for (int i = start; i <= 12; ++i)
{
if (!used[i])
{
used[i] = true;
dfs(u + 1, i + 1);
used[i] = false;
}
}
}
int main()
{
e[1][2] = e[1][5] = 1;
e[2][1] = e[2][3] = e[2][6] = 1;
e[3][2] = e[3][4] = e[3][7] = 1;
e[4][3] = e[4][8] = 1;
e[5][1] = e[5][6] = e[5][9] = 1;
e[6][2] = e[6][5] = e[6][7] = e[6][10] = 1;
e[7][3] = e[7][6] = e[7][8] = e[7][11] = 1;
e[8][4] = e[8][7] = e[8][12] = 1;
e[9][5] = e[9][10] = 1;
e[10][6] = e[10][9] = e[10][11] = 1;
e[11][7] = e[11][10] = e[11][12] = 1;
e[12][8] = e[12][11] = 1;
dfs(0, 1);
cout << ans << endl; // 答案116
return 0;
}
8H:四平方和(21分编程)
题目描述:
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符号表示乘方的意思)
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
解析代码(循环)
题目分析:
分析:直接四层循环可能会超时,可以考虑先将两个数能构成的平方和保存在map里面,如果在前两层循环的时候,发现剩下的数并不能由两个数的平方构成,就直接continue跳过~否则就判断第三层循环,然后用sqrt(num - a * a - b * b - c * c)算出最后一个数temp,看它是否为整数,如果是整数就输出。这里三层循环+判断也能过了。哈希甚至过不了民间测试。
cpp复制代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
int i, j, k, p;
int n, m;
int o;
cin >> n;
int flag = 0;
for (i = 0; i * i < n; ++i)
{
for (j = 0; j * j < n; ++j)
{
for (k = 0; k * k < n; ++k)
{
m = n - i * i - j * j - k * k;
o = sqrt(m);
if (o * o == m)
{
flag = 1;
break;
}
}
if (flag)
break;
}
if (flag)
break;
}
printf("%d %d %d %d\n", i, j, k, o);
return 0;
}
9I:交换瓶子(23分编程)
题目描述:
有N个瓶子,编号 1 ~ N,放在架子上。
比如有5个瓶子:
2 1 3 5 4
要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5
对于这么简单的情况,显然,至少需要交换2次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。
输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
例如,输入:
5
3 1 2 5 4
程序应该输出:
3
再例如,输入:
5
5 4 3 2 1程序应该输出:
2
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
解法一及代码(贪心)
贪心:如果第 i 个位置的数不是 i (假设为x),那么就直接将这个数与第 x 个位置的数相交换:b[x] = x b[i] = b[x];这样每次操作一定可以至少让一个瓶子回到它原本的位置。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 10010;
int n;
int b[N];
bool st[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> b[i];
int cnt = 0;
for (int i = 1; i <= n; ++i)
{
if (!st[i])
{
++cnt;//判环个数
for (int j = i; !st[j]; j = b[j])
{
st[j] = true;
}
}
}
printf("%d\n", n - cnt);//次数=数组元素总个数-环个数
return 0;
}