1
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
…
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路
简单题,不说了
题解
#include<iostream>
using namespace std;
int main(){
int dp[1000];
dp[1] = 1;
dp[2] = 3;
int sum = 4;
for(int i = 3;i<=100;i++){
dp[i] = dp[i-1] + i;
sum+=dp[i];
}
cout <<sum<<endl;
}
2
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路
太简单了,不说了
#include<iostream>
using namespace std;
int sum;
int main(){
for(int i = 1;i<=100;i++){
for(int j = i;j<=100;j++){
sum += j;
if(sum == 236){
cout <<i<<endl;
break;
}
}
sum = 0;
}
}
3
B DEF
A + — + ------- = 10
C GHI
(如果显示有问题,可以参见【图1.jpg】)
这个算式中AI代表19的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
思路
注意选double 全排列即可
题解
#include<iostream>
using namespace std;
int sum,ans;
int b[100];
double a[100];
void dfs(int x){
if(x == 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){
ans++;
}
return;
}
for(int i = 1;i<10;i++){
if(!b[i]){
a[x] = i;
b[i] = 1;
dfs(x+1);
b[i] = 0;
}
}
}
int main(){
dfs(0);
cout<<ans<<endl;
}
4
快速排序
思路
简单说就是拿一个数开始比,小的放左边,大的放右边
题解
4.5 由于蓝桥杯取消了填空,就不做了
6
如下的10个格子
±-±-±-+
| | | |
±-±-±-±-+
| | | | |
±-±-±-±-+
| | | |
±-±-±-+
(如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
此题还是回溯,从第一个格子开始填,并用vis数组记录一个结果中填的数是否被用过
dfs前进行判断,判断四个方向是否可以填
题解
#include<iostream>
using namespace std;
int mp[5][5];
int cnt;
bool vis[10];
int abs(int x){
return x>0?x:-x;
}
bool check(int x,int y,int v){
if(x > 0){
if(abs(mp[x-1][y] - v) == 1)
return false;
if(y > 0 && abs(mp[x-1][y-1] - v) ==1)
return false;
if(y < 3 && abs(mp[x-1][y+1] - v) == 1)
return false;
}
if(y > 0 && abs(mp[x][y-1] - v) == 1)
return false;
return true;
}
void dfs(int x){
if(x == 11){
cnt++;
return;
}
for(int i = 0;i<10;i++){
if(!vis[i]){
vis[i] = true;
if(check(x/4,x%4,i)){
mp[x/4][x%4] = i;
dfs(x+1);
}
vis[i] = false;
}
}
}
int main(){
mp[0][0] = 100;
dfs(1);
cout <<cnt<<endl;
return 0;
}
7
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题解
#include<iostream>
#include<cstring>
using namespace std;
int a[5];
bool vis[3][4];
int n;
int dir[4][2] = {{0,-1},{-1,0},{1,0},{0,1}};
int ans;
int flag;
void dfs1(int x,int y){
for(int i = 0;i<4;i++){
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if(tx >= 0 && tx < 3 && ty >= 0 && ty < 4 &&vis[tx][ty]){
vis[tx][ty] = 0;
flag++;
dfs1(tx,ty);
}
}
}
void dfs(int k){
if(n == 5){
memset(vis,0,sizeof(vis));
int sx,sy;
for(int i = 0;i<5;i++){
int x = (a[i] - 1) / 4;
int y = (a[i] - 1) % 4;
vis[x][y] = true;
if(i == 4){
vis[x][y] = false;
sx = x;
sy = y;
}
}
flag = 1;
dfs1(sx,sy);
if(flag == 5){
ans++;
}
}
else{
for(int i = k+1;i<=12;i++){
a[n++] = i;
dfs(i);
n--;
}
}
}
int main(){
dfs(0);
cout <<ans<<endl;
return 0;
}
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
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms
题解
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int vis[5000005];
int main()
{
int n;
scanf("%d", &n);
for(int i=0; i*i <= n; ++i)
for(int j=0; i*i + j*j <= n; ++j)
vis[i*i+j*j] = 1;
for(int i=0; i*i <= n; ++i)
for(int j=i; i*i + j*j <= n; ++j)
{
if(vis[n - i*i - j*j])
{
for(int k=j; i*i + j*j + k*k <= n; ++k)
{
double x = sqrt((double)(n-i*i-j*j-k*k));
if(x == (int)x) return 0*printf("%d %d %d %d\n", i, j, k, (int)x);
}
}
}
return 0;
}
二分思路
#include<iostream>
#include<algorithm>
using namespace std;
const int N=5e6+10;
int n,cnt;
struct node{
int v,c,d;
bool operator < (const node &t)const //重载< 因为sort给结构体排序,括号中的const表示参数a对象不会被修改,最后的const表明调用函数对象不会被修改
{
if(v!=t.v)return v<t.v;
if(c!=t.c)return c<t.c;
if(d!=t.d)return d<t.d;
}
}node[N];
int main()
{
cin>>n;
for(int c=0;c*c<=n;c++)
for(int d=c;d*d+c*c<=n;d++)
node[cnt++]={c*c+d*d,c,d};
sort(node,node+cnt);
for(int a=0;a*a<=n;a++)
for(int b=a;a*a+b*b<=n;b++)
{
int l=0,r=cnt-1;
int t=n-a*a-b*b;
while(l<r)// a<b,c<d,ab之后二分查找cd的值,所以一定是最小升序
{
int mid=l+r>>1;
if(node[mid].v>=t)r=mid;
else l=mid+1;
}
if(node[l].v==t)
{
cout<<a<<" "<<b<<" "<<node[l].c<<" "<<node[l].d;
return 0;
}
}
}
9
交换瓶子
交换瓶子
来源: 第七届蓝桥杯省赛C++B组
算法标签 图论 环 置换群 贪心
题目描述
有 N 个瓶子,编号 1∼N,放在架子上。
比如有 5 个瓶子:
2 1 3 5 4
要求每次拿起 2 个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5
对于这么简单的情况,显然,至少需要交换 2 次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式
第一行包含一个整数 N,表示瓶子数量。
第二行包含 N 个整数,表示瓶子目前的排列状况。
输出格式
输出一个正整数,表示至少交换多少次,才能完成排序。
数据范围
1≤N≤10000,
1
输入样例1:
5
3 1 2 5 4
1
2
输出样例1:
3
1
输入样例2:
5
5 4 3 2 1
1
2
输出样例2:
2
#include<iostream>
using namespace std;
int a[100],n,ans;
bool vis[100];
int main(){
cin >>n;
for(int i = 1;i<=n;i++){
cin >>a[i];
}
for(int i = 1;i<=n;i++){
if(!vis[i]){
ans++;
for(int j = i;!vis[j];j = a[j]){
vis[j] = true;
}
}
}
cout <<n-ans<<endl;
}
10
有点。。。