问题描述
答案:2520 有同学肯定要问,那要是我偏让你输出这2520个具体的排列呢?那没办法了,上代码: 问题描述
答案:13107200 问题描述
答案:14 解决方案二: 如果题目还要求输出具体的合法序列,则程序可添加为如下内容: 问题描述
答案:2018 问题描述 样例说明
分析:由于数据范围并不大,且计算过程仅仅是3次取余操作,那么在极限情况下,也仅仅是执行100 0000×3次取余操作,以及不多于100 0000次的累加操作。所以可以直接采用暴力法,代码如下: 问题描述 评测用例规模与约定
分析:题目明确了输入是一个单词,且仅含小写字母,那么处理起来就很简单了。我们直接接受一个字符串str,然后遍历该字符串中的每个字符,将每个字符都与字符’a’进行做差(目的是得到当前字符在小写字母表中的位置,如’a’为0,’b’为1,’c’为2,……以此类推),注意此时得到的差值是一个int型。由于凯撒密码的加密方案是往后移3个位置,那么我们就需要将做差得到的这个差值+3。 接下来就是还原工作了。我们可以直接将得到的temp与字符’a’进行求和运算,此时temp就由int型变成了char型(如0+‘a’=‘a’,1+‘a’=‘b’,2+‘a’=‘c’,……以此类推)。这一过程的代码描述如下: 求解本题的完整代码如下: 问题描述 评测用例规模与约定
分析:这是一道典型的模拟类题目。我们的求解思路很简单:首先是根据输入的规格求出对应螺旋矩阵,然后再通过输入的待求位置直接得到答案即可。 问题描述 样例说明
分析:这是一道典型的动态规划题目,和蓝桥杯 校内模拟赛 奇怪的数列以及蓝桥杯 历届试题 波动数列类似,搜索算法只能对[1,10]的范围内的数据起作用,要想得满分必然要用动态规划。 问题描述 评测用例规模与约定
分析:题目这意思已经很明显了——求最小生成树。 方法一:Prim算法求解
方法二:Kruskal算法求解 问题描述 评测用例规模与约定
分析:仍在研究中……
1.排列字母LANQIAO
将LANQIAO中的字母重新排列,可以得到不同的单词,如LANQIAO、AAILNOQ等,注意这7个字母都要被用上,单词不一定有具体的英文意义。
请问,总共能排列如多少个不同的单词。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解决思路:其实这就是一道高中时器的选择题,考点是“排列组合”。
如果题目问你:7个不同字母进行排列,问你能组合出多少种不同的序列,你可以很容易得到答案为:7!=7×6×5×4×3×2×1=5040。但是别急!!!本题的答案并不是5040,因为本题给的7个字母并不是完全不同的,因为其中有两个“A”。因此在刚才的计算中,我们将两个字母“A”视为了不同的字母。解决办法很简单,那就是再除以2,即正确答案应该是:7! / 2 = 7×6×5×4×3×2×1 / 2 = 5040 /2 = 2520。#include<iostream> #include<algorithm> using namespace std; int main() { char chs[]={'A','A','I','L','N','O','Q'}; int sum=0; cout<<"具体的排列情况如下:"<<endl; do{ sum++; for(int i=0;i<7;i++) cout<<chs[i]; cout<<endl; }while(next_permutation(chs,chs+7)); cout<<"共"<<sum<<"个"<<endl; return 0; }
2.单位变换
在计算机存储中,12.5MB是多少字节?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解决办法:作为一名程序员,你至少要知道:1MB(兆字节) = 1024KB(千字节),1KB = 1024B(字节)。
因此对于本题而言,可以直接用电脑自带的“计算器”软件计算:12.5×1024×1024=13107200。
3.括号的合法序列
由1对括号,可以组成一种合法括号序列:()。
由2对括号,可以组成两种合法括号序列:()()、(())。
由4对括号组成的合法括号序列一共有多少种?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解决方案一:
4对括号这个数据并不算大,所以可以直接硬算:
深度为1时:()()()();
深度为2时:(())()()、()(())()、()()(())、(()()())、(()())()、()(()())、(())(());
深度为3时:((()))()、()((()))、((())())、(()(()))、((()()));
深度为4时:(((())))。
从长远的方向来看,指不定下一次省赛就将这道题变成了编程大题,因此我们还是要给出本题的代码实现:#include<iostream> using namespace std; int sum,n; void dfs(int left,int right) //用left和right分别表示(和),由于给定的(和)最初是匹配的 { if(left == n){ //故所有的非法情况都是由)导致的,因此当(都出现了就不会非法 sum++; return; } dfs(left+1,right); //根据贪心思想,合法的括号组合方式必然是以(开始 if(left > right) dfs(left,right+1); //基于前面的结果,此后在满足left>right时得到的括号序列都将是合法的 } int main() { cin>>n; dfs(0,0); cout<<sum<<endl; return 0; }
#include<iostream> #include<cstring> using namespace std; const int N=1000; char chs[N]; int sum,n; void dfs(int left,int right) { if(left == n){ sum++; cout<<chs; for(int i=strlen(chs);i<n*2;i++) cout<<")"; cout<<endl; return; } chs[left+right]='('; dfs(left+1,right); chs[left+right]=' '; if(left > right){ chs[left+right]=')'; dfs(left,right+1); } } int main() { cin>>n; cout<<"总的括号匹配序列有:"<<endl; dfs(0,0); cout<<"共"<<sum<<"个"<<endl; return 0; }
4.2019个节点的无向连通图
一个包含有2019个结点的无向连通图,最少包含多少条边?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解决办法:一个具有n个节点的无向连通图,其最少含有的边为n-1(其实就是这个图的生成树)。
5.反倍数
给定三个整数 a, b, c,如果一个整数既不是 a 的整数倍也不是 b 的整数倍还不是 c 的整数倍,则这个数称为反倍数。
请问在 1 至 n 中有多少个反倍数。
输入格式
输入的第一行包含一个整数 n。
第二行包含三个整数 a, b, c,相邻两个数之间用一个空格分隔。
输出格式
输出一行包含一个整数,表示答案。
样例输入
30
2 3 6
样例输出
10
以下这些数满足要求:1, 5, 7, 11, 13, 17, 19, 23, 25, 29。
评测用例规模与约定
对于 40% 的评测用例,1 <= n <= 10000。
对于 80% 的评测用例,1 <= n <= 100000。
对于所有评测用例,1 <= n <= 1000000,1 <= a <= n,1 <= b <= n,1 <= c <= n。#include <iostream> using namespace std; int count(int n,int a,int b,int c) { int ans=0; for(int i=1;i<=n;i++) if(i%a!=0 && i%b!=0 && i%c!=0) ans++; return ans; } int main() { int n,a,b,c; cin>>n>>a>>b>>c; cout<<count(n,a,b,c); return 0; }
6.凯撒密码
给定一个单词,请使用凯撒密码将这个单词加密。
凯撒密码是一种替换加密的技术,单词中的所有字母都在字母表上向后偏移3位后被替换成密文。即a变为d,b变为e,…,w变为z,x变为a,y变为b,z变为c。
例如,lanqiao会变成odqtldr。
输入格式
输入一行,包含一个单词,单词中只包含小写英文字母。
输出格式
输出一行,表示加密后的密文。
样例输入
lanqiao
样例输出
odqtldr
对于所有评测用例,单词中的字母个数不超过100。
这里有一点需要注意:+3可能导致这个值大于26(这样在还原的时候,就会得到非小写字母类字符),因此我们在这里还需要对+3后的这个值进行一个取余运算,代码描述如下:for(int i-0;i<str.length();i++) int temp = (str[i]-'a'+3)%26;
for(int i-0;i<str.length();i++){ int temp = (str[i]-'a'+3)%26; str[i] = 'a' + temp; }
#include<iostream> #include<string> using namespace std; string Caesar(string str) { for(int i=0;i<str.length();i++) str[i]='a'+(str[i]-'a'+3)%26; return str; } int main() { string str; cin>>str; cout<<Caesar(str)<<endl; return 0; }
7.螺旋矩阵
对于一个 n 行 m 列的表格,我们可以使用螺旋的方式给表格依次填上正整数,我们称填好的表格为一个螺旋矩阵。
例如,一个 4 行 5 列的螺旋矩阵如下:
1 2 3 4 5
14 15 16 17 6
13 20 19 18 7
12 11 10 9 8
输入格式
输入的第一行包含两个整数 n, m,分别表示螺旋矩阵的行数和列数。
第二行包含两个整数 r, c,表示要求的行号和列号。
输出格式
输出一个整数,表示螺旋矩阵中第 r 行第 c 列的元素的值。
样例输入
4 5
2 2
样例输出
15
对于 30% 的评测用例,2 <= n, m <= 20。
对于 70% 的评测用例,2 <= n, m <= 100。
对于所有评测用例,2 <= n, m <= 1000,1 <= r <= n,1 <= c <= m。
问题的关键点就在于怎么求出这个螺旋矩阵?直接解释很难说,请同学们直接看代码(附详细解释,走一遍就能懂)。需要注意的是一定要对count==m*n时进行特殊判断,防止由于正方形矩阵的出现而陷入死循环。#include<iostream> #include<iomanip> using namespace std; const int N=1005; int ary[N][N]; void create(int n,int m) { int U=1,R=m,D=n,L=1; //分别表示矩阵的上、右、下、左边界限 int i=1,j=1,count=1; while(count<=m*n) { for(;j<R;j++) ary[i][j]=count++; //从左往右填充 for(;i<D;i++) ary[i][j]=count++; //从上往下填充 for(;j>L;j--) ary[i][j]=count++; //从右往左填充 for(;i>U;i--) ary[i][j]=count++; //从下往上填充 U++,R--,D--,L++; i++,j++; if(count == m*n) ary[i][j]=count++; //防止当m=n时陷入死循环 } } int main() { int n,m,r,l; cin>>n>>m>>l>>r; create(n,m); cout<<ary[l][r]<<endl; return 0; }
8.摆动序列
如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列。即 a[2i]<a[2i-1], a[2i+1]>a[2i]。
小明想知道,长度为 m,每个数都是 1 到 n 之间的正整数的摆动序列一共有多少个。
输入格式
输入一行包含两个整数 m,n。
输出格式
输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
样例输入
3 4
样例输出
14
以下是符合要求的摆动序列:
2 1 2
2 1 3
2 1 4
3 1 2
3 1 3
3 1 4
3 2 3
3 2 4
4 1 2
4 1 3
4 1 4
4 2 3
4 2 4
4 3 4
评测用例规模与约定
对于 20% 的评测用例,1 <= n, m <= 5;
对于 50% 的评测用例,1 <= n, m <= 10;
对于 80% 的评测用例,1 <= n, m <= 100;
对于所有评测用例,1 <= n, m <= 1000。
博主对于动态规划一直都在学习中,因此在看到这道题时,我觉得很有必要为其单独写一篇题解(因为够难,所以也够资格为其单独写题解),这是链接【蓝桥杯】省塞模拟赛 摆动序列(动态规划),下面就直接为Ctrl C党贴满分代码了:#include<iostream> using namespace std; const int N=1005; const int MOD=10000; int dp[N][N]; int DP(int m,int n) { for(int i=1;i<=n;i++) dp[1][i]=n-i+1; //初始化dp数组 for(int i=2;i<=m;i++){ if(i&1) //如果i为奇数 for(int j=n;j>=1;j--) dp[i][j]=(dp[i-1][j-1]+dp[i][j+1])%MOD; else //否则则为偶数 for(int j=1;j<=n;j++) dp[i][j]=(dp[i-1][j+1]+dp[i][j-1])%MOD; } return m&1?dp[m][1]:dp[m][n]; //根据m的奇偶性返回最后的答案 } int main() { int m,n; cin>>m>>n; cout<<DP(m,n)<<endl; return 0; }
9.村庄通电
2015年,全中国实现了户户通电。作为一名电力建设者,小明正在帮助一带一路上的国家通电。
这一次,小明要帮助 n 个村庄通电,其中 1 号村庄正好可以建立一个发电站,所发的电足够所有村庄使用。
现在,这 n 个村庄之间都没有电线相连,小明主要要做的是架设电线连接这些村庄,使得所有村庄都直接或间接的与发电站相通。
小明测量了所有村庄的位置(坐标)和高度,如果要连接两个村庄,小明需要花费两个村庄之间的坐标距离加上高度差的平方,形式化描述为坐标为 (x_1, y_1) 高度为 h_1 的村庄与坐标为 (x_2, y_2) 高度为 h_2 的村庄之间连接的费用为
sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2))+(h_1-h_2)*(h_1-h_2)。
在上式中 sqrt 表示取括号内的平方根。请注意括号的位置,高度的计算方式与横纵坐标的计算方式不同。
由于经费有限,请帮助小明计算他至少要花费多少费用才能使这 n 个村庄都通电。
输入格式
输入的第一行包含一个整数 n ,表示村庄的数量。
接下来 n 行,每个三个整数 x, y, h,分别表示一个村庄的横、纵坐标和高度,其中第一个村庄可以建立发电站。
输出格式
输出一行,包含一个实数,四舍五入保留 2 位小数,表示答案。
样例输入
4
1 1 3
9 9 7
8 8 6
4 5 4
样例输出
17.41
对于 30% 的评测用例,1 <= n <= 10;
对于 60% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 1000,0 <= x, y, h <= 10000。
最小生成树算法主要有两个:prim算法、kruskal算法。如果对这两个算法都不熟悉,建议先学习下再来刷这副本。殿堂级学习通道:【算法与数据结构】—— 最小生成树(Prim算法、Kruskal算法)
学习完上面的文章后,下面直接给出用两个不同算法求解本题的完整代码(含详细注释):#include<iostream> #include<algorithm> #include<vector> #include<cmath> using namespace std; const int N=1005; struct Node{ int x,y,h; Node(){ } Node(int a,int b,int c) { x=a,y=b,h=c; } }; struct Edge{ int x,y; float cost; Edge(){ } Edge(int a,int b,float c) { x=a,y=b,cost=c; } }; bool cmp(Edge e1,Edge e2) { return e1.cost<e2.cost; } float map[N][N]; //户与户之间的距离产生的费用(由于所有户均互通,因此可以直接用邻接矩阵) class Prim{ private: int n; //村庄数 float cost; //存放所有户都通电的最小代价 Node node[N]; //存放每户的坐标位置 vector<Edge> e; //存放在执行insert后插入的边 bool vis[N]; //标记某户是否已经通电了 void create() //计算map { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) map[i][j]=map[j][i]=sqrt(pow(node[i].x-node[j].x,2)+pow(node[i].y-node[j].y,2))+pow(node[i].h-node[j].h,2); } void insert(int point) { vis[point]=true; for(int i=1;i<=n;i++) if(!vis[i]) e.push_back(Edge(point,i,map[point][i])); sort(e.begin(),e.end(),cmp); } public: Prim(int num) //num表示总的村庄个数 { n=num; int x,y,h; for(int i=1;i<=n;i++){ cin>>x>>y>>h; node[i]=Node(x,y,h); } create(); } void run(int start) { insert(start); int selected=1; //seleced表示当前已经连通了多少户 while(selected<n) { for(int i=0;i<e.size();i++){ if(!vis[e[i].y]){ cost+=e[i].cost; insert(e[i].y); selected++; break; } } } } float getCost() { return cost; } }; int main() { int n;cin>>n; Prim prim(n); //构建prim prim.run(1); //从第1个节点出发 printf("%.2fn",prim.getCost()); //注意格式化输出最终的cost return 0; }
#include<iostream> #include<vector> #include<cmath> #include<algorithm> using namespace std; const int N=1010; struct Edge{ //用于表示边的信息 int x,y; //x,y分别表示某两户居民 float cost; //cost则表示这之间电线的造价 Edge(){ } //无参构造函数 Edge(int a,int b,float c) //构造函数 { x=a,y=b,cost=c; } }; struct Node{ int x,y,h; Node(){ } Node(int a,int b,int c) { x=a,y=b,h=c; } }; bool cmp(Edge e1,Edge e2) //用于sort函数排序时的规则 { return e1.cost<e2.cost; } class UnionFindSet{ //并查集类,用于连通两个节点以及判断图中的所有节点是否连通 private: static const int MAX=N; int pre[MAX]; //pre数组用于存放某个节点的上级 int rank[MAX]; //rank数组用于降低关系树的高度 int start,n; //start和n分别用于指示并查集里节点的起点和终点 public: void init(int a,int b) //初始化并查集 { start=a,n=b; for(int i=start;i<=n;i++){ pre[i]=i; rank[i]=1; } } int findPre(int x) //寻找某个节点的上级 { if(pre[x]==x) return x; return pre[x]=findPre(pre[x]); } bool isSame(int x,int y) //判断某两个节点是否连通 { return findPre(x)==findPre(y); } bool unite(int x,int y) //判断两个节是否连通,如果未连通则将其连通并返回真,否则返回假 { x=findPre(x); y=findPre(y); if(x==y) return false; if(rank[x] > rank[y]) pre[y]=x; else{ if(rank[x]==rank[y]) rank[y]++; pre[x]=y; } return true; } bool isOne() //判断整个无向图中的所有节点是否连通 { int temp=findPre(start); for(int i=start+1;i<=n;i++) if(findPre(i)!=temp) return false; return true; } }; class Kruskal{ //Kruskal算法:求解无向连通图中的最小生成树 private: int n; //n表示住户个数 static const int MAX=N; float cost; //存放所有户都通电的最小代价 Node node[N]; //存放每户的坐标位置 vector<Edge> e; //存放录入的无向连通图的所有边 UnionFindSet u; //并查集:抽象实现Graphnew,并完成节点间的连接工作以及判断整个图是否连通 void create() //计算所有住户之间的造价 { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) e.push_back(Edge(i,j,sqrt(pow(node[i].x-node[j].x,2)+pow(node[i].y-node[j].y,2))+pow(node[i].h-node[j].h,2))); } public: Kruskal(int num) //num表示总的住户个数 { n=num; int x,y,h; for(int i=1;i<=n;i++){ cin>>x>>y>>h; node[i]=Node(x,y,h); } create(); sort(e.begin(),e.end(),cmp);//对录入的边进行排序 u.init(1,n); //初始化并查集u } void run() //求解录入的无向连通图的最小生成树 { for(int i=0;i<e.size();i++){//按序遍历所有边 if(u.unite(e[i].x,e[i].y)) cost+=e[i].cost; //如果当前边能够被接受,则说明这条边属于最小生成树 if(u.isOne()) break; //一旦并查集的连通分支数为1,则说明求出了最小生成树 } } float getCost() { return cost; } }; int main() { int n;cin>>n; Kruskal kruskal(n); //构建kruskal kruskal.run(); //开始计算 printf("%.2fn",kruskal.getCost()); //注意格式化输出最终的cost return 0; }
10.种树问题
小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗。
小明和朋友们一共有 n 个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n 个。他们准备把自己带的树苗都植下去。
然而,他们遇到了一个困难:有的树苗比较大,而有的位置挨太近,导致两棵树植下去后会撞在一起。
他们将树看成一个圆,圆心在他们找的位置上。如果两棵树对应的圆相交,这两棵树就不适合同时植下(相切不受影响),称为两棵树冲突。
小明和朋友们决定先合计合计,只将其中的一部分树植下去,保证没有互相冲突的树。他们同时希望这些树所能覆盖的面积和(圆面积和)最大。
输入格式
输入的第一行包含一个整数 n ,表示人数,即准备植树的位置数。
接下来 n 行,每行三个整数 x, y, r,表示一棵树在空地上的横、纵坐标和半径。
输出格式
输出一行包含一个整数,表示在不冲突下可以植树的面积和。由于每棵树的面积都是圆周率的整数倍,请输出答案除以圆周率后的值(应当是一个整数)。
样例输入
6
1 1 2
1 4 2
1 7 2
4 1 2
4 4 2
4 7 2
样例输出
12
对于 30% 的评测用例,1 <= n <= 10;
对于 60% 的评测用例,1 <= n <= 20;
对于所有评测用例,1 <= n <= 30,0 <= x, y <= 1000,1 <= r <= 1000。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算