1.煤球数目
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
…
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解题思路:
#include <iostream>
using namespace std;
int main(){
int sum=0,n;
cin >> n;
for(int i = 1;i <= n;i++)
{
sum += i * (i + 1) / 2;
}
cout << sum << endl;
return 0;
}//171700
2.生日蜡烛(枚举)
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:1 2 3 4 5 6……这一个等差数列的前n项和为(1+n)*n/2,设从a岁开始过生日,到了b岁一共吹熄了236根蜡烛。即为:(a+b)(b-a+1)/2=236
解题思路1:
#include <iostream>
using namespace std;
int main(){
for(int i = 1;i <= 100;i++){
for(int j = i;j <= 100;j++){
if((i + j) * ( j - i + 1) / 2 == 236)
cout << i << " " << j << endl;
}
}
return 0;
}//26
3.凑算式(全排列)
B DEF
A + --- + ------- = 10
C GHI
(如果显示有问题,可以参见【图1.jpg】)
这个算式中AI代表19的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
示例:意思为求1,2,3,4的全排列:next_permutation(a,a+4)
解题思路1:
#include<iostream>
#include<algorithm>
using namespace std;
double a[9]={1,2,3,4,5,6,7,8,9};
int c;
int main(){
while(next_permutation(a,a+9)){
if(a[0] + a[1] / a[2] + ( a[3] * 100 + a[4] * 10 + a[5] ) / ( a[6] * 100 + a[7] * 10 + a[8]) == 10.0)
c++;
}
cout << c << endl;
return 0;
} //29
解题思路2:
#include<iostream>
using namespace std;
int a[9] = {0};
int ans = 0;
bool judge(int a[]){//判断是否算式和为10
double x = a[0] + a[1] * 1.0 / a[2] + ( a[3] * 100 + a[4] * 10 + a[5]) * 1.0 / ( a[6] * 100 + a[7] * 10 + a[8]);
if(x == 10.0) return 1;
return 0;
}
bool check(int num){//检测a[num]是否有重复
for(int i = num-1;i >= 0;i--){
if(a[i] == a[num]) return 0;
}
return 1;
}
void dfs(int num){//就是最基本的9个数全排列,在结束条件里用judge()做判断
if(num>8){
if(judge(a))
ans++;
return;
}
for(int i = 1;i < 10;i++){
a[num] = i;
if(check(num)){
dfs(num+1);
}
}
}
int main(){
dfs(0);
cout << ans;
return 0;
}
解题思路3:
#include<iostream>
using namespace std;
int main(void){
int count = 0;
for(int a = 1;a < 10;a++){
for(int b = 1;b < 10;b++){
if(a == b) continue;
for(int c = 1;c < 10;c++){
if(a == c || c == b) continue;
for(int d = 1;d < 10;d++){
if(a == d || d == b || c == d)continue;
for(int e = 1;e < 10; e++){
if(e == a || e == b || e == c || e == d)continue;
for(int f = 1; f < 10;f++){
if(f == a || f == b || f == c || f == d || f == e)continue;
for(int g = 1;g < 10;g++){
if(g == a || g == b || g == c || g == d || g == e || g == f)continue;
for(int h = 1;h < 10;h++){
if(h == a || h == b|| h == c || h == d || h == e || h == f || h == g)continue;
for(int i = 1; i < 10;i++){
if(i == a || i == b || i == c || i == d || i == e || i == f || i == g || i == h)continue;
int t1 = a * c * ( 100 * g + 10 * h + i );
int t2 = b * (100 * g + 10 * h + i);
int t3 = c * (100 * d + 10 * e + f);
int t4 = 10 * c * (100 * g + 10 * h + i);
if( t1 + t2 + t3 == t4)count++;
}
}
}
}
}
}
}
}
}
cout << count << endl;
return 0;
}
4.快速排序
排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。
下面的代码是一种实现,请分析并填写划线部分缺少的代码。
#include <stdio.h>
#include <stdlib.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){//分区0 11
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);
}
swap(a,p,j);//填空 swap(a,p,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;
}
注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。
5.抽签
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';//数字加上 英文字符表示 对应的
// printf("%s\n", b[i]); //填空位置
f(a,k+1,m-i,b);
}
}
int main(){
int a[N] = {4,2,2,1,1,3};
char b[BUF];
f(a,0,M,b);
return 0;
}
仔细阅读代码,填写划线部分缺少的内容。
注意:不要填写任何已有内容或说明性文字。
解题思路:
思路:一共选M个人,m经过选择记录剩下可选人数,M-m为已经选择的人数
M-m+j为新加入的人在b数组中的下标。这题在填空之后可以利用总共101行这个条件进行验证,即:在f函数每次printf输出的时候进行统计个数,最后输出sum检测是否为101。注意不要多填分号。
答案:f(a,k+1,m-i,b),因为这里i = j .应该 f(a,k+1,m-j,b)也可以。
6.方格填数
如下的10个格子
+--+--+--+
| | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | |
+--+--+--+
(如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解题思路:
#include <iostream>
#include <algorithm>
using namespace std;
int a[11]= {11111,0,1,2,3,4,5,6,7,8,9};
int judge(){
if(abs(a[1]-a[2]) == 1 || abs(a[1]-a[4]) == 1 || abs(a[1]-a[5]) == 1 || abs(a[1] - a[6]) == 1)
return 0;
else if(abs(a[2]-a[5]) == 1 || abs(a[2]-a[6]) == 1 || abs(a[2]-a[7]) == 1 || abs(a[2]-a[3]) == 1)
return 0;
else if(abs(a[3]-a[6]) == 1 || abs(a[3]-a[7]) == 1)
return 0;
else if(abs(a[4]-a[5]) == 1 || abs(a[4]-a[8]) == 1 || abs(a[4]-a[9]) == 1)
return 0;
else if(abs(a[5]-a[6]) == 1 || abs(a[5]-a[8]) == 1 || abs(a[5]-a[9]) == 1 || abs(a[5]-a[10]) == 1)
return 0;
else if(abs(a[6]-a[7]) == 1 || abs(a[6]-a[9]) == 1 || abs(a[6]-a[10]) == 1)
return 0;
else if(abs(a[7]-a[10]) == 1)
return 0;
else if(abs(a[8]-a[9]) == 1)
return 0;
else if(abs(a[9]-a[10]) == 1)
return 0;
return 1;
}
int main(){
int sum = 0;
do{
if(judge())
sum++;
}while(next_permutation(a + 1,a + 11));
cout << sum;
return 0;
}
解题思路2:
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int flag[3][4]; //表示哪些可以填数
int mpt[3][4]; //填数
bool visit[10];
int ans = 0;
void init(){ //初始化
int i,j;
for(i = 0 ; i < 3 ; i ++)
for(j = 0 ; j < 4 ; j ++)
flag[i][j] = 1;
flag[0][0] = 0;
flag[2][3] = 0;
}
void Solve(){
int dir[8][2] = { 0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};
int book = true;
for(int i = 0 ; i < 3 ; i ++){
for(int j = 0 ; j < 4; j ++){
//判断每个数周围是否满足
if(flag[i][j] == 0)continue;
for( int k = 0 ; k < 8 ; k ++){
int x,y;
x = i + dir[k][0];
y = j + dir[k][1];
if(x < 0 || x >= 3 || y < 0 || y >= 4 || flag[x][y] == 0) continue;
if(abs(mpt[x][y] - mpt[i][j]) == 1) book = false;
}
}
}
if(book){
ans++;
}
}
void dfs(int index){
int x,y;
x = index / 4;
y = index % 4;
if( x == 3){
Solve();
return;
}
if(flag[x][y]){
for(int i = 0 ; i < 10 ; i ++){
if(!visit[i]){
visit[i] = true;
mpt[x][y] = i;
dfs(index+1);
visit[i] = false;
}
}
}else{
dfs(index+1);
}
}
int main(){
init();
dfs(0);
printf("%d\n",ans);
return 0;
}
7.剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
8.8四平方和
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多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
解题思路:
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int a = 0;a <= 2237;a++){
if( a * a > n) continue;
for(int b = a; b <= 2237;b++){
if( a * a + b * b > n) break;
for(int c = b;c <= 2237;c++){
if( a * a + b * b + c * c > n) break;
for(int d = c;d <= 2237;d++){
if(a * a + b * b + c * c + d * d > n) break;
if(a * a + b * b + c * c + d * d == n){
cout << a << " " << b << " " << c << " " << d <<endl;
return 0;
}
}
}
}
}
return 0;
}
9.交换瓶子
有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
解题思路:
思路:因为要交换次数最少,所以自然是每次选中一个瓶子,把它交换到它该在的位置,这样次数最少,那么就只是一个选择排序问题了。
#include <iostream>
using namespace std;
int main(){
int n,a[10000],sum=0;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
}
int minn;
for(int i = 0; i < n; i++){
minn = i;
for(int j = i + 1; j < n; j++){
if( a[minn] > a[j]){
minn = j;
}
}
if(minn != i){
sum++;
int t = a[i];
a[i] = a[minn];
a[minn] = t;
}
}
cout << sum << endl;
return 0;
}
最大比例
X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:
16,24,36,54
其等比值为:3/2
现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。
输入格式:
第一行为数字 N (0<N<100),表示接下的一行包含N个正整数
第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额
要求输出:
一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数
测试数据保证了输入格式正确,并且最大比例是存在的。
例如,输入:
3
1250 200 32
程序应该输出:
25/4
再例如,输入:
4
3125 32 32 200
程序应该输出:
5/2
再例如,输入:
3
549755813888 524288 2
程序应该输出:
4/1
一般没有这个水平做到这儿来 放弃了