一、试题A:煤球数目
二、试题B: 生日蜡烛
三、试题C:凑算式
四、试题D:快速排序
五、试题E:抽签
六、试题F:方格填数
七、试题G:剪邮票
八、试题H:四平方和
九、试题I:交换瓶子
十、试题J:最大比例
一、试题A:煤球数目
水题,但是要看清题(请填表示煤球总数目的数字)
(错误)代码如下:
#include<iostream> using namespace std; int main(){ int cnt = 1; for(int i = 2; i <= 100; i ++ ){ cnt += i; cout<< i << " " << cnt << endl; } cout<<cnt; return 0; }
这个算的是第100项的值
(正确)代码如下:
请填表示煤球总数目的数字
#include<iostream> using namespace std; int main(){ int cnt = 1,sum = 1; for(int i = 2; i <= 100; i ++ ){ cnt += i; sum += cnt; cout<< i << " " << cnt << endl; } cout<<sum; return 0; }
二、试题B: 生日蜡烛
水题:看清题目(从多少岁开始过生日)
代码如下:
#include<iostream> using namespace std; int main(){ for(int i = 1; i <= 100; i ++ ){ int sum = 0; for(int j = i; j <= 100; j ++ ){ sum += j; if(sum == 236){ cout<<i; return 0; } } } return 0; }
三、试题C:凑算式
解题思路:
- 看见这种公式题,先想想怎么转化
3.因为A-I取(1-9)任意一个,需要全排列
do { if(check()) Ans++; }while(next_permutation(a, a+9));
(错误)代码如下:
a[6] * a[7] * a[8] ❌,这是一个三位数,其他雷同
#include<iostream> #include<algorithm> using namespace std; int a[] = {1,2,3,4,5,6,7,8,9}; int ans; bool check(){ int x = a[1] * a[6] * a[7] * a[8]; int y = a[2] * a[3] * a[4] * a[5]; int z = (10 - a[0]) * a[2] * a[6] * a[7] * a[8]; if(x + y == z) return true; return false; } int main(){ do{ if(check()) ans ++; }while(next_permutation(a,a + 9)); cout<<ans; return 0; }
(正确)代码如下:
#include<iostream> #include<algorithm> using namespace std; int a[] = {1,2,3,4,5,6,7,8,9}; int ans; bool check(){ int x = a[1] * (a[6] * 100 + a[7] * 10 + a[8]); int y = a[2] * (a[3] * 100 + a[4] * 10 + a[5]); int z = (10 - a[0]) * a[2] * (a[6] * 100 + a[7] * 10 + a[8]); if(x + y == z) return true; return false; } int main(){ do{ if(check()) ans ++; }while(next_permutation(a,a + 9)); cout<<ans; return 0; }
注意:
如果数据过大,尽量转换为除法的形式
需要变换的代码: int z = (10 - a[0]) * a[2] * (a[6] * 100 + a[7] * 10 + a[8]); if(x + y == z) return true; return false; 变换为: int z = a[2] * (a[6] * 100 + a[7] * 10 + a[8]); if((x + y) % z != 0) return false; if((x + y) / z == (10 - a[0])) return true; return false;
代码如下:
#include<iostream> #include<algorithm> using namespace std; int a[] = {1,2,3,4,5,6,7,8,9}; int ans; bool check(){ int x = a[1] * (a[6] * 100 + a[7] * 10 + a[8]); int y = a[2] * (a[3] * 100 + a[4] * 10 + a[5]); int z = a[2] * (a[6] * 100 + a[7] * 10 + a[8]); if((x + y) % z != 0) return false; if((x + y) / z == (10 - a[0])) return true; return false; } int main(){ do{ if(check()) ans ++; }while(next_permutation(a,a + 9)); cout<<ans; return 0; }
四、试题D:快速排序(待补)
快速排序 排序在各种场合经常被用到。 快速排序是十分常用的高效率的算法。 其思想是:先选一个“标尺”, 用它把整个队列过一遍筛子, 以保证:其左边的元素都不大于它,其右边的元素都不小于它。 这样,排序问题就被分割为两个子区间。 再分别对子区间排序就可以了。 下面的代码是一种实现,请分析并填写划线部分缺少的代码。 #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; } 注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。
五、试题E:抽签(待补)
抽签 X星球要派出一个5人组成的观察团前往W星。 其中: A国最多可以派出4人。 B国最多可以派出2人。 C国最多可以派出2人。 .... 那么最终派往W星的观察团会有多少种国别的不同组合呢? 下面的程序解决了这个问题。 数组a[] 中既是每个国家可以派出的最多的名额。 程序执行结果为: DEFFF CEFFF CDFFF CDEFF CCFFF CCEFF CCDFF CCDEF BEFFF BDFFF BDEFF BCFFF BCEFF BCDFF BCDEF .... (以下省略,总共101行) #include <stdio.h> #define N 6 #define M 5 #define BUF 1024 void f(int a[], int k, int m, char b[]) { int i,j; if(k==N){ b[M] = 0; if(m==0) printf("%s\n",b); return; } for(i=0; i<=a[k]; i++){ for(j=0; j<i; j++) b[M-m+j] = k+'A'; ______________________; //填空位置 } } int main() { int a[N] = {4,2,2,1,1,3}; char b[BUF]; f(a,0,M,b); return 0; } 仔细阅读代码,填写划线部分缺少的内容。 注意:不要填写任何已有内容或说明性文字。
六、试题F:方格填数
题目要求:
连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
解题思路:
- 先把格子填充一遍,考虑后面需要判断一个格子周围八个格子是否与它相邻,所以把格子扩充一圈,防止周围格子影响答案
- 走到头就需要转到下次层的首位置
(DFS)代码如下:
#include<iostream> #include<algorithm> using namespace std; const int N = 10; int n; int g[N][N]; bool st[N]; int ans; bool check(int x,int y) { for(int i = x - 1; i <= x + 1; i ++ ) { for(int j = y - 1; j <= y + 1; j ++ ) { if(abs(g[x][y] - g[i][j]) == 1) { return false; } } } return true; } void dfs(int x,int y) { if(x == 3 && y == 4) { ans ++; return ; } for(int i = 0; i < 10; i ++ ) { if(st[i]) continue; g[x][y] = i; if(!check(x,y)) { g[x][y] = -10; continue; } st[i] = true; if(y == 4) { dfs(x + 1,1); }else{ dfs(x,y + 1); } g[x][y] = -10; st[i] = false; } } int main() { for(int i = 0; i < 5; i ++ ) { for(int j = 0; j < 6; j ++ ) { g[i][j] = -10; } } dfs(1,2); cout<<ans; return 0; }
七、试题G:剪邮票
解题思路:
- 一共12个小格子,要求取5个
- 用全排列枚举所有情况
- dfs遍历,如果只有一个连通块的话,就可取
(DFS)代码如下:
#include<iostream> #include<algorithm> #include<cstring> using namespace std; #define mm(a,x) memset(a,x,sizeof a) const int N = 10; int a[] = {0,0,0,0,0,0,0,1,1,1,1,1}; int g[N][N]; int ans; int dx[4] = {0,1,0,-1}; int dy[4] = {1,0,-1,0}; void dfs(int x,int y){ g[x][y] = 0; for(int i = 0; i < 4; i ++ ){ int a = x + dx[i]; int b = y + dy[i]; if(a < 0 || a > 2 || b < 0 || b > 3 ) continue; if(g[a][b] == 0) continue; dfs(a,b); } } bool check(){ for(int i = 0; i < 3; i ++ ){ for(int j = 0; j < 4; j ++ ){ g[i][j] = a[i * 4 + j]; } } int cnt = 0; for(int i = 0; i < 3; i ++ ){ for(int j = 0; j < 4; j ++ ){ if(g[i][j] == 1){ dfs(i,j); cnt ++; } } } if(cnt == 1) return true; return false; } int main() { do{ if(check()) ans ++; }while(next_permutation(a,a + 12)); cout<<ans; return 0; }
八、试题H:四平方和
例如,输入:
5
则程序应该输出:
0 0 1 2
再例如,输入:
12
则程序应该输出:
0 2 2 2
再例如,输入:
773535
则程序应该输出:
1 1 267 838
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。</xxx>
提交时,注意选择所期望的编译器类型。
注意:
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
输出第一个就行,之间结束
解题思路:
由于0 <= a <= b <= c <= d,可得 a * a <= n/4,b * b <=n/3,c * c <= n/2, d * d <= n
方法一:暴力求解(TLE)
#include<iostream> #include<algorithm> #include<cstring> using namespace std; #define mm(a,x) memset(a,x,sizeof a) int n; int main() { scanf("%d",&n); for(int a = 0; a * a <= n/4; a ++ ){ for(int b = a; b * b <= n/3; b ++ ){ for(int c = b; c * c <= n/2; c ++ ){ for(int d = c; d * d <= n; d ++ ){ if(a * a + b * b + c * c + d * d == n){ cout<< a << " " << b << " " << c <<" " << d; return 0; } } } } } return 0; }
方法二:
散列求解:
参考大佬的题解orz
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; #define mm(a,x) memset(a,x,sizeof a) const int N = 1e8 + 10; int n; int h[N]; int main() { scanf("%d",&n); //打表,找出1 - n,所有完全平方数两两之和,如果存在只记第一次出现(题目要求找出字典序小的) for(int c = 0; c * c <= n/2; c ++){ for(int d = c; c * c + d * d <= n; d ++){ //防止i = 0时在后面判断查找跳过 i = 0的情况 if(!h[c * c + d * d]) h[c * c + d * d] = c + 1; } } //0<= a <= b <= c <= d,可以得出a^2 <= n / 4, a^2 + b^ 2 <= n / 2; for(int a = 0; a * a <= n/4; a ++ ){ for(int b = a; a * a + b * b <= n/2; b ++ ){ int t = n - a * a - b * b; if(h[t]){ int c = h[t] - 1; //防止开根号后因为精度关系,向下取整,例:25 开根号得到4.99999向下取整为4; //int d = (sqrt(t - c * c) + 1e-4); int d = (int)(sqrt(t - c * c) * 1.0); printf("%d %d %d %d",a,b,c,d); return 0; } } } return 0; }
九、试题I:交换瓶子
例如,输入:
5
3 1 2 5 4
程序应该输出:
3
再例如,输入:
5
5 4 3 2 1
程序应该输出:
2
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。</xxx>
提交时,注意选择所期望的编译器类型。
解题思路:
1.交换问题:首先想到组合数学环的问题
组合数圈的题解
代码如下:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; #define mm(a,x) memset(a,x,sizeof a) const int N = 1e4 + 10; bool st[N]; int a[N]; int n,ans; void dfs(int u){ if(st[u]) return ; st[u] = true; dfs(a[u]); } int main() { cin >> n; for(int i = 1; i <= n; i ++ ){ cin >> a[i]; } for(int i = 1; i <= n; i ++ ){ if(!st[i]){ ans ++; dfs(i); } } cout << n - ans; return 0; }
十、试题J:最大比例(待补)
例如,输入:
3
1250 200 32
程序应该输出:
25/4
再例如,输入:
4
3125 32 32 200
程序应该输出:
5/2
再例如,输入:
3
549755813888 524288 2
程序应该输出:
4/1
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。</xxx>
提交时,注意选择所期望的编译器类型。