[蓝桥杯]2016蓝桥省赛B组题目及详解
/*———————————————————————————————————————————————————————————
【结果填空题】T1 (分值:3)
题目:煤球数目 有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。 1 * (1)
2 *** (3)
3 ****** (6)
4 ********** (10)
5 ..............(15)
————————————————————————————————————————————————————————————*/
// /**
* pre 定义上一层
* plus 定义增量差值 */
#include<iostream>
using namespace std ;
int main(int argc, char const *argv[])
{
int pre = ; //
int plus = ; //
long sum = ;
for (int k = ; k <= ; ++k)
{
sum += (pre+plus) ;
pre = pre + plus ;//sum+=pre
plus++ ;
}
cout << sum << endl ; return ;
}
//结果:171700 /*———————————————————————————————————————————————————————————
【结果填空题】T2 (分值:5)
题目:生日蜡烛 某君从某年开始每年都举办一次生日party,
并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
————————————————————————————————————————————————————————————*/
//
/*
思路:236 i ~ j
for(i:100)
for(j:100)
等差数列求和:(i+j)/2*(j-i-1)
(a0+a0*(n-1)*d/2)*n*/ #include<iostream>
using namespace std ;
int main()
{
//枚举两个年龄
for (int i = ; i < ; ++i)
{
for (int j = i; j < ; ++j)
{
if((i*j)*(j-i-)/==)
cout << i << " "<< j << endl ;
}
} //枚举生日举办次数
for (int i = ; i < ; ++i)
{
int t = i*(i-)/ ;
if((-t)%i==)
{
//输出首项
cout << (-t)/i << " " << i << endl ;
}
} return ;
} /*———————————————————————————————————————————————————————————
【结果填空题】T3 (分值:11)
题目:凑算式 B DEF
A + --- + ------- = 10
C GHI (如果显示有问题,可以参见【图1.jpg】)
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
————————————————————————————————————————————————————————————*/
//
//全排列
#include<iostream>
#include<math.h> using namespace std ;
int a[] = {,,,,,,,,} ;
int ans ;
bool check()
{
int x = a[] * + a[] * + a[] ;
int y = a[] * + a[] * + a[] ;
if((a[]*y + a[]*x) % (y*a[])== && a[]
+ (a[]*y + a[]*x)/(y*a[]==)) return true ;
return false ;
} //递归回溯生成全排列 适用于无重复元素的情况
//考虑前k位,前面已经排定
void f(int k)
{
if(k==)
{
//其中一种排列已经生成
if(check()) ans++ ;
}
//从k往后的每个数字都可以放在k位
for (int i = k; i < ; ++i)
{
{int t=a[i]; a[i]=a[k]; a[k]=t;}
f(k+) ; //递归
{int t=a[i]; a[i]=a[k]; a[k]=t;} //回溯
}
} int main()
{
f() ;
cout << ans << endl ;
return ;
} //思路二 next_permutation() #include<iostream>
#include<math.h> using namespace std ;
int a[] = {,,,,,,,,} ;
int ans ;
bool check()
{
int x = a[] * + a[] * + a[] ;
int y = a[] * + a[] * + a[] ;
if((a[]*y + a[]*x) % (y*a[])== && a[]
+ (a[]*y + a[]*x)/(y*a[]==)) return true ;
return false ;
} int main()
{
do{
if(check()) ans++ ;
}while(next_permutation(a,a+)) ; cout << ans << endl ;
return ;
} /*———————————————————————————————————————————————————————————
【代码填空题】T4 (分值:9)
题目:快速排序
排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。 下面的代码是一种实现,请分析并填写划线部分缺少的代码。
————————————————————————————————————————————————————————————*/
//
#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; //i指向大于x ——>找大
int j = r + ; //j指向小于等于x ——>找小
int x = a[p];
while(){
while(i<r && a[++i]<x);
while(a[--j]>x);
if(i>=j) break;
swap(a,i,j);
}
/*代码填空处
swap(a,p,j) ; //
______________________; */
return j;
} void quicksort(int a[], int p, int r)
{
if(p<r){
int q = partition(a,p,r); //q为标尺
quicksort(a,p,q-);
quicksort(a,q+,r);
}
} int main()
{
int i;
int a[] = {,,,,,,,,,,,};
int N = ; quicksort(a, , N-); //排序 for(i=; i<N; i++)
printf("%d ", a[i]);
printf("\n"); return ;
} /*———————————————————————————————————————————————————————————
【代码填空题】T5 (分值:13)
题目:抽签 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
/**
* k = 数组的下标
* m代表人数,初始为5
* b缓冲字符串
*/ void f(int a[], int k, int m, char b[])
{
int i,j; if(k==N){
b[M] = ; //字符串结尾的标志
if(m==) {printf("%s\n",b); ans++ ;}
return;
}
//递归
for(i=; i<=a[k]; i++){ //试着将k国家,排除i人
for(j=; j<i; j++) b[M-m+j] = k+'A'; ////填充buf,有i人就填i个国家符号(k+'A')
/*代码填空处
f(a,k+1,m-i,b) ;
______________________; */
f(a,k+,m-i,b) ;
}
}
int main()
{
int a[N] = {,,,,,};
char b[BUF];
f(a,,M,b);
printf("%d\n",ans) ;
return ;
} /*———————————————————————————————————————————————————————————
【结果填空题】T6 (分值:19)
题目:方格填数
如下的10个格子
+--+--+--+
| | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | |
+--+--+--+ (如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案? 请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
————————————————————————————————————————————————————————————*/
// 全排列 + 检查
#include<iostream>
using namespace std ; int a[] = {,,,,,,,,,} ;
int ans ; void check()//检查
{
if(abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== ||
abs(a[] - a[])== ||
abs(a[] - a[])== || abs(a[] - a[])== || abs(a[] - a[])== || abs(a[] - a[])== ||)
return false ;
return true ;
} /*考虑第k个位置,一般从0开始*/
void f(int k)//递归函数
{
//出口
if(k==)
{
bool b = check() ; //检查
if(b)
ans++ ;
return ;
} for (int i = k; i < ; ++i)
//尝试将位置i与位置k交换,以此确定k位的值
{
int t = a[i] ;
a[i] = a[k] ;
a[k] = t ;
}
f(k+) ;
//回溯
{
int t = a[i] ;
a[i] = a[k] ;
a[k] = t ;
} } int main()
{
f() ; //初始化
cout << ans << endl ; return ;
} //思路2 使用二维数组
/* 3*4 ——> 5*6
-10-10-10-10-10
+--+--+--+
| | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | |
+--+--+--+
-10-10-10-10-10 */
#include<iostream>
using namespace std ; int a[][] ;
int vis[] ;
int ans ; bool check(int i ,int y) //检查
{
for (int x = x-; x<= i+; ++x)
{
for (int y = j-; y <= j+; ++y)
{
if(abs(a[x][y]-a[i][j])==)
return false ;
}
}
return true ;
} //全排列
void f(int k,int y)
{
if(x== & y == )
{
ans++ ;
return ;
}
//从0-9中抓一个
for (int i = ; i < ; ++i)
{
if(vis[i]==) //i没有没用过
{
a[x][y] = i ; //填数
if(!check(x,y)) //不合法,恢复并continue
{
a[x][y] = - ;
continue ;
}
vis[i] = ; if(y ==)
f(x+,) ; //换行
else
f(x,y+) ; //继续填右侧的格子
{
vis[i] = ;
a[x][y] = - ;
}
}
}
} //初始化
void init()
{
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
{
a[i][j] = - ; //初始化格式
}
}
} int main(int argc, char const *argv[])
{
init() ; //初始化
f(,) ; //递归调用
cout << ans <<endl ; //打印输出
return ;
}
/*本思路可以防止下标越界的问题*/ /*———————————————————————————————————————————————————————————
【结果填空题】T7 (分值:19)
题目:剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
| | | | |
+--+--+--+--+
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。 请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
————————————————————————————————————————————————————————————*/
// /*
1 2 3 4
5 6 7 8
9 10 11 12 思路1:每个格子作为起点,dfs连五张,去重->结果 思路2:暴力枚举,所有的五张组合,检查它们是不是一个连通块。 */
// 12/13 寒假作业 12/5 dfs /*思路1: 生成的方法有太多的重复,效率低下
//此题和13年剪格子有相似之处,但是那个题的限制条件是格子数值之和为总和的一半,此题则限制只能是5个格子
//单纯的dfs无法解决T字型连通方案
//本题的解决办法是,找出任意5个格子,判断是否连通*/
#include <algorithm>
#include <iostream> using namespace std; int ans; bool check(int arr[]); void dfs(int g[][], int i, int j); int main(int argc, const char *argv[]) {
int per[] = {, , , , , , , , , , , };
do {
if (check(per))
ans++;
} while (next_permutation(per, per + ));
cout << ans << endl;
return ;
} bool check(int arr[]) {
int g[][];
memset(g, , sizeof(g));
//将相应位置标注为1
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
if (arr[i * + j] == )g[i][j] = ;
}
}
// 经典连通块计算
int cnt = ;
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
if (g[i][j] == ) {
dfs(g, i, j);
cnt++;
}
}
}
return cnt == ;
} void dfs(int g[][], int i, int j) {
g[i][j] = ;
if (i + <= && g[i + ][j] == ) dfs(g, i + , j);
if (i - >= && g[i - ][j] == ) dfs(g, i - , j);
if (j + <= && g[i][j + ] == ) dfs(g, i, j + );
if (j - >= && g[i][j - ] == ) dfs(g, i, j - );
} //思路2:
#include <algorithm>
#include <iostream>
#include <set> using namespace std; int a[]={,,,,,,,,,,,};//它的每个排列代表着12选5的一个方案
int ans;
void dfs(int g[][],int i , int j){
g[i][j]=;
if(i->=&&g[i-][j]==)dfs(g,i-,j);
if(i+<=&&g[i+][j]==)dfs(g,i+,j);
if(j->=&&g[i][j-]==)dfs(g,i,j-);
if(j+<=&&g[i][j+]==)dfs(g,i,j+);
}
bool check(){
int g[][];
// 将某个排列映射到二维矩阵上
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
if(a[i*+j]==) g[i][j]=;
else g[i][j]=;
}
}
int cnt=;//连通块的数目
// g上面就有5个格子被标记为1,现在才用dfs做连通性检查,要求只有一个连通块
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
if(g[i][j]==){
dfs(g,i,j);
cnt++;
}
}
}
return cnt==;
}
set<string> s1;
void a2s(string &s){
for (int i = ; i < ; ++i) {
s.insert(s.end(),a[i]+'');
}
}
bool isExist(){
string a_str;
a2s(a_str);
if(s1.find(a_str)==s1.end()){
s1.insert(a_str);
return false;
} else
return true;
}
void f(int k){
if(k==){
if(!isExist()&&check()){
ans++;
}
}
for (int i = k; i < ; ++i) {
{int t=a[i];a[i]=a[k];a[k]=t;}
f(k+);
{int t=a[i];a[i]=a[k];a[k]=t;}
}
}
int main(int argc, const char *argv[]) {
f();
printf("%d",ans);
//string _s;
//a2s(_s);
//cout<<_s<<endl;
return ;
} //思路3:
#include <algorithm>
#include <iostream> using namespace std; //它的每个排列代表着12选5的一个方案
int a[] = {, , , , , , , , , , , };
int ans; void dfs(int g[][], int i, int j)
{
g[i][j] = ;
if (i - >= && g[i - ][j] == )dfs(g, i - , j);
if (i + <= && g[i + ][j] == )dfs(g, i + , j);
if (j - >= && g[i][j - ] == )dfs(g, i, j - );
if (j + <= && g[i][j + ] == )dfs(g, i, j + );
} bool check(int path[])
{
int g[][];
// 将某个排列映射到二维矩阵上
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
{
if (path[i * + j] == ) g[i][j] = ;
else g[i][j] = ;
}
}
int cnt = ;//连通块的数目
// g上面就有5个格子被标记为1,现在才用dfs做连通性检查,要求只有一个连通块
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
{
if (g[i][j] == )
{
dfs(g, i, j);
cnt++;
}
}
}
return cnt == ;
} bool vis[]; void f(int k, int path[])
{
if (k == ) {
if (check(path))
{
ans++;
}
}
for (int i = ; i < ; ++i)
{
if (i>&&a[i]==a[i-]&&!vis[i-])continue;//现在准备选取的元素和上一个元素相同,但是上一个元素还没被使用 if(!vis[i]){//没有被用过的元素可以抓入到path
vis[i]=true;//标记为已访问
path[k]=a[i];//将a[i]填入到path[k]中
f(k + , path);//递归
vis[i]=false;//回溯
} }
} int main(int argc, const char *argv[])
{
int path[];
f(, path);
printf("%d", ans);
return ;
} /*———————————————————————————————————————————————————————————
【代码编程题】T8 (分值: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 请严格按要求输出,不要画蛇添足地打印类似:
“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,
不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>,
不能通过工程设置而省略常用头文件。 提交时,注意选择所期望的编译器类型。 ————————————————————————————————————————————————————————————*/
//枚举+优化
//优化:采用缓存来空间换时间 /*思路1:
枚举abcd
for(a) 0~a^2
for(b) 0~b^2
for(c) 0~c^2
for(d) 0~d^2 */
#include<iostream>
#include<cstdio>
#include<map>
int N ; using namespace std ; int main()
{
scanf("%d",&N) ;
//
for (int c = ; c*c <= N/; ++c)
{
for (int d = c; c*c+d*d <= N ; ++d)
{
if(cache.find(c*c+d*d)==cache.end())
cache[c*c+d*d] = c ;
}
//
for (int a = ; a*a<= N/; ++a)
{
for (int b = a; a*a+c*c <= N/; ++b)
{
if(cache.find(N-a*a+b*b)!=cache.end()) ;
int c = cache[N-(a*a+b*b+c*c)] ;
int d = int(sqrt(N-(a*a+b*b+c*c)) ;
printf("%d %d %d %d\n",a,b,c,d) ;
return ;
}
}
}
return ;
} /*———————————————————————————————————————————————————————————
【代码编程题】T9 (分值: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 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,
不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>,
不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
————————————————————————————————————————————————————————————*/
/*
3 2 1 5 4
[1] [2] [3] [4] [5] */ // 贪心
#include <iostream> using namespace std;
int n;
int a[];
int ans; int pos(int x)
{
for (int i = ; i <= n; ++i)
{
if (a[i] == x)return i;
}
return -;
} void swap(int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
} void printArr() {
for (int i = ; i <= n; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
} int main(int argc, const char *argv[])
{
// 处理输入
scanf("%d", &n);
for (int i = ; i <= n; ++i)
{
scanf("%d", &a[i]);
}
//遍历i:1-N
for (int i = ; i <= n; ++i)
{
//如果a[i]=i,已经到位
if (a[i] == i)continue;
//否则先找到i在a中的位置pos(i)和i位交换——swap(a,pos(i),i)
else
{
swap(pos(i), i);
ans++;
}
}
//printArr();
printf("%d\n", ans);
return ;
} /*———————————————————————————————————————————————————————————
【代码编程题】T10 (分值:31)
题目:最大比例 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 资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms 请严格按要求输出,不要画蛇添足地打印类似:
“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,
不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>,
不能通过工程设置而省略常用头文件。 提交时,注意选择所期望的编译器类型。
————————————————————————————————————————————————————————————*/
// /*
等比数列:a0、a1、a2、a3、a4
等比数列的性质:
a3 p
—— ——> (———)^2
a0 q */
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector> using namespace std ;
typedef long long LL ;
int N ;
LL data[] ; struct Ratio{
LL x,y ;
Ratio(LL _x,LL _y):x(_x),(_y)
{
LL _gcd = gcd(x,y) ;
x /= _gcd ;
y /= _gcd ;
}
LL gcd(LL a,LL b)
{
if(b==) return a ;
return gcd(b,a%b) ;
}
} ;
//存储比值
vector<Ratio> ratios ; int main()
{
//处理输入
scanf("%d",&n) ;
for (int i = ; i < N; ++i) //扫描输入数据
{
scanf("%lld",&data[i]) ;
} //排序
sort(data,data+N) ; //两两比值,以分数形式存储,vector
for (int i = ; i < N-; ++i)
{
if(data[i+]!=data[i])//去重
ratios.push_back(Ratio(data[i+],data[]i)) ;
} /*对第一个比值开1-..pow(极限为40)次方作为基数,
如果这个基数的分子、分母的k1
k2次方恰好是其他比值的分子分母的话,基数就是答案*/
for (int pow = ; pow <= ; ++pow)
{
Ratio ra0 = ratios[] ;
LL x = ra0.x ;
LL y = ra0.y ;
LL fx = extract(x,pow) ; //对
LL fy = extract(y,pow) ; //
if(fx==- |\ fy ==-) continue ; //开不出,continue
//能开,就要确认所有比值的分子是fx的整数次方,所有比值的分母是fy的整数次方
//计px=getPow(xx,fx),py=getPow(yy,fy),要求必须是整数且px==py bool all_match = true ;
//
for (int i = ; i < ratios.size(); ++i)
{
LL xx = ratios[i].x ;
LL yy = ratios[i].y ;
LL px = getPow(xx,fx) ;
LL py = getPow(yy,fy) ; if(px == - || py == - || px != py)
{
all_match = false ;
break ;
}
}
if(all_match)
{ Ratio ans = Ratio(fx,fy) ;
cout << ans.x << "/" << ans.y << endl ;
}
return ;
} return ;
} //优化 + 完善
#include <stdio.h>
#include <iostream>
#include <vector>
#include <map> using namespace std;
typedef long long LL;
int N;
LL data[]; //结构体
struct Ratio
{
LL x, y; Ratio(LL _x, LL _y) : x(_x), y(_y)
{
LL _gcd = gcd(x, y);
x /= _gcd;
y /= _gcd;
} LL gcd(LL a, LL b)
{
if (b == )return a;
return gcd(b, a % b);
}
}; vector<Ratio> ratios;
map<LL, map<LL,LL> > all_ex;//all_ex[x][pow]==x开pow次方
map<LL, map<LL,LL> > all_log;//all_log[x][y]==log_y_x,y的多少次方是x? void init() //预处理
{
for (int i = ; i < 1e6; ++i)
{//底数
LL cur=(LL)i*i;
int pow=;
while(cur<1e12)
{
all_ex[cur][pow]=i;
all_log[cur][i]=pow;
pow++;
cur*=i;
}
}
} /**
* 对x开pow次方
* @param x
* @param pow
* @return
*/
LL extract(LL x,LL pow)
{
if(pow==)return x;
if(x==)return ;
if(all_ex[x].find(pow)!=all_ex[x].end())//意味着x可以开pow整数次方
return all_ex[x][pow];
else
return -;
} /**
* 求log_base_x
* @param base
* @param x
* @return
*/ LL log(LL base,LL x)
{
if(base==x)return ;
if(all_log[x].find(base)!=all_log[x].end())//意味着可以得打一个k,base的k次方是x
return all_log[x][base];
return -;
} int main(int argc, const char *argv[])
{
init();
freopen("/Users/zhengwei/CLionProjects/lanqiaobei2019/2016_C_A/data10/in8.txt","r",stdin);
//处理输入
scanf("%d", &N);
for (int i = ; i < N; ++i)
{
scanf("%lld", &data[i]);
}
//排序
sort(data, data + N);
//处理只有两项的特殊情况
if(N==)
{
Ratio ans = Ratio(data[], data[]);
cout << ans.x << "/" << ans.y << endl;
return ;
} //求两两比值,以分数形式存储,vector
for (int i = ; i < N - ; ++i)
{
if (data[i + ] != data[i])//去重
ratios.push_back(Ratio(data[i + ], data[i]));
} //对第一个比值开1~..pow(极限为40).次方,作为基数,如果这个基数也是其他比值的基数的话,该基数就是答案
for (int pow = ; pow <= ; ++pow)
{
Ratio ra0 = ratios[];
LL x = ra0.x;
LL y = ra0.y;
LL base_x = extract(x, pow);//对x开pow次方,作为基数,去尝试
LL base_y = extract(y, pow);//对y开pow次方,作为基数,去尝试
if (base_x == - || base_y == -)continue;//开不出,continue
//能开:就要去确认所有比值的分子是fx的整数次方,所有比值的分母是fy的整数次方
//计px=getPow(xx,base_x),py=getPow(yy,base_y),要求必须是整数且px==py
bool all_match = true;
for (int i = ; i < ratios.size(); ++i)
{
LL xx = ratios[i].x;
LL yy = ratios[i].y;
LL log_x = log(base_x,xx);
LL log_y = log(base_y,yy);
if(base_y==&&yy==)log_y=log_x;
if (log_x == - || log_y == - || log_x != log_y) {
all_match = false;
break;
}
}
if (all_match)
{
Ratio ans = Ratio(base_x, base_y);
cout << ans.x << "/" << ans.y << endl;
return ;
} }
return ;
} //【2016年B组C++小结】
/**********************************************************
* 01【结果填空】煤球数目 :枚举+简单计算
* 02【结果填空】生日蜡烛 :等差数列求和
* 03【结果填空】凑算式 :全排列
* 04【代码填空】快速排序 :裸题
* 05【代码填空】抽签 :递归,明确参数的含义及参数的变化方向
* 06【填空填空】方格填数 :全排列 + check
* 07【结果填空】剪邮票(**) :dfs解决不了T型组合,全排列+dfs求矩阵中的连通块
* 08【编程题】四平方和 :枚举+优化
* 09【编程题】交换瓶子(**) :贪心
* 10【编程题】最大比例(***) :数论、等比数列、预处理
**********************************************************/
[蓝桥杯]2016蓝桥省赛B组题目及详解的更多相关文章
- [蓝桥杯]2017蓝桥省赛B组题目及详解
/*——————————————————————————————————————————————————————————— [结果填空题]T1 (分值:5) 题目:购物单 小明刚刚找到工作,老板人很好 ...
- [蓝桥杯]2014蓝桥省赛B组题目及详解
/*——————————————————————————————————————————————————————————— [结果填空题]T1 题目:啤酒和饮料 啤酒每罐2.3元,饮料每罐1.9元.小 ...
- [蓝桥杯]2013蓝桥省赛B组题目及详解
/*——————————————————————————————————————————————————————————— 题目:2013 高斯日记T-1 问题描述: 大数学家高斯有一个好习惯:无论如 ...
- [蓝桥杯]2015蓝桥省赛B组题目及详解
/*——————————————————————————————————————————————————————————— [结果填空题]T1 题目:奖券数目 有些人很迷信数字,比如带“4”的数字,认 ...
- 2016年第七届蓝桥杯c/c++省赛B组
2016年第七届蓝桥杯c/c++省赛B组 声明:以下答案是我自己做的.不能保证正确,须要參考正确答案的请到其它地方找. 第一题 :煤球数目 题目叙述: 有一堆煤球,堆成三角棱锥形.详细: 第一层放1个 ...
- 蓝桥杯2016年省赛C/C++大学A组
网友年龄 某君新认识一网友. 当问及年龄时,他的网友说: "我的年龄是个2位数,我比儿子大27岁, 如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄" 请你计算:网友的年龄一 ...
- 2019年第十届蓝桥杯【C++省赛B组】
试题 A: 组队 本题总分:5 分 作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员,组成球队的首发阵容.每位球员担任 1 号位至 5 号位时的评分如下表所示.请你计算首发阵容 ...
- 2016年第七届蓝桥杯【C++省赛B组】F、G、H、J 题解
F. 方格填数 #深搜 题意 有\(10\)个格子,填入0~9的数字.要求:连续的两个数字不能相邻.(左右.上下.对角都算相邻),求可能的填数方案数. +--+--+--+ | | | | +--+- ...
- 2017年第八届蓝桥杯【C++省赛B组】B、C、D、H 题解
可能因为我使用暴力思维比较少,这场感觉难度不低. B. 等差素数列 #暴力 #枚举 题意 类似:\(7,37,67,97,127,157\) 这样完全由素数组成的等差数列,叫等差素数数列. 上边的数列 ...
随机推荐
- FragmentTabHostAutoDemo【FragmentTabHost可滑动的选项卡】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用FragmentTabHost实现顶部选项卡(可滑动的效果)展现. 效果图 代码分析 1.该Demo中采用的是FragmentT ...
- 使用sklearn时cannot import name MLPClassifier的解决办法
scikit-learn v0.17只有BernoulliRBM,没有MLPClassifier. 只需要把scikit-learn升级到v0.18即可. 在控制台输入下面任一个命令即可: conda ...
- .NET Core和Swagger 生成 Api 文档
测试/生产环境的BUG 这里更新一下在本地调试正常,在INT/PROD上抛错,错误信息为: */**/*.xml(Swagger json file) 文件找不到,在startup 里builder ...
- Oracle的坑,你是否踩过?----安装篇
作为一个职场的新人,之前都是接触Sql server 数据库比较多,Oracle这方面基本没有接触过,然后这次公司刚好有个项目用到了Oracle数据库,然后就打算学习一下这方面的知识.然后昨天安装Or ...
- mybatis 参数格式异常-- Error querying database. Cause: java.lang.NumberFormatException: For input string
mybatis中 <if></if>标签中进行判断时,如果传入的时字符格式和数字进行判断需要将数字进行转译,否则默认是数字和数字进行比较,这是就会出现参数格式异常如<if ...
- windows如何安装memcached
官网上并未提供 Memcached 的 Windows 平台安装包,我们可以使用以下链接来下载,你需要根据自己的系统平台及需要的版本号点击对应的链接下载即可: 32位系统 1.2.5版本:http:/ ...
- Vue.js实现注册功能
编写html,通过vue-resource.js库向后台提交数据 <!DOCTYPE html> <html lang="en"> <head> ...
- openlayers三:添加图片和图标
openlayers添加图片是指: 添加在地图上的图片会跟随地图同步放大缩小 而添加图标是指: 添加在地图上的图片不会跟随地图同步放大缩小 添加图片: 首先初始化图片图层: initImageLaye ...
- 数据库微信特殊表情编码django设置
#settings.py DATABASES = { 'default': { 'OPTIONS': { "init_command":"SET foreign_key_ ...
- 理解SignalR
ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现即时通信(即:客户端(Web页面)和服务器端可以互相实时的通知消息及调用方法),即时通讯W ...