问题 A: 分离出整数n从右边数第k个数字,递归实现
思路:将整数作为字符串容易判断其位数与k关系。只有一位时若k=1则次数即为答案,否则第k个数不存在。k大于次数位数时第k个数不存在。其他情况递归k-1次每次使字符串长度-1(丢弃末末位字符),返回最后一位即为答案。
代码:
#include <bits/stdc++.h>
using namespace std;
char digit(string s,int k){
if(s.length()==1){//只有一位时,k=1可返回此数,否则第k个数字不存在
if(k==1) return s[s.length()-1];
else return '0';
}
if(k>s.length()) return '0';//k超过整数位数,第k个数字不存在
if(k>1){//递归字符串长度每次-1,k-1次后返回末尾字符
return digit(s.substr(0,s.length()-1),k-1);
}
if(k==1) return s[s.length()-1];
}
int main(){
//freopen("/config/workspace/test/test","r",stdin);
string s;
int k;
cin>>s>>k;
char ans=digit(s,k);
cout<<ans;
return 0;
}
问题 B: Xu Xiake in Henan Province
思路:计数,输出对应字符串即可,没什么特别的。(但是otaku有被内涵到 笑死)
代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int t;
cin>>t;
while(t--){
int count=0;
for(int i=0;i<4;i++){
int temp;
cin>>temp;
if(temp!=0) count++;
}
if(count==0) cout<<"Typically Otaku"<<endl;
else if(count==1) cout<<"Eye-opener"<<endl;
else if(count==2) cout<<"Young Traveller"<<endl;
else if(count==3) cout<<"Excellent Traveller"<<endl;
else if(count==4) cout<<"Contemporary Xu Xiake"<<endl;
}
return 0;
}
问题 C: Fibonacci Sequence
思路:直接递归会超时,所以就在数组里算吧。
代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int n;
cin>>n;
long long a[91];
a[1]=a[2]=1;
for(int i=3;i<=n;i++){
a[i]=a[i-1]+a[i-2];
}
cout<<a[n]<<endl;
return 0;
}
问题 D: 一只小蜜蜂
思路:可以递归,但是容易超时,还是像斐波那契数列那样先算出来比较好。当起始地点和终点相差为1的时,只有一种方法;当相差为2时,有两种方法,而除去相差为1与相差为2的情况后,其余的都可以使用前两者的方法数相加得到结果。
代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int n;
cin>>n;
long long way[51];
way[2]=1;way[3]=2;
for(int i=4;i<=50;i++){
way[i]=way[i-1]+way[i-2];//直接算出前五十个(类似斐波拉契数列)
}
while(n--){
int a,b;
cin>>a>>b;
if(a>b) cout<<0<<endl;
else cout<<way[b-a+1]<<endl;
}
return 0;
}
问题 E: 【蓝桥杯2020初赛】七段码
思路:dfs搜索所有状态,判断每种状态是否满足条件。判断的方法是把每条灯管当作一个节点,编号(a b c d e f g → 1 2 3 4 5 6 7),连边建图,对搜索出的亮灯方案使用并查集判断点亮的灯管是否在同一个集合。答案是80.
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 10;
int ans;
int p[N];
bool st[N];
int e[N][N];
int find(int x){
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
void dfs(int u){
if(u == 8) {
for (int i = 1; i <= 7; i ++) p[i] = i;
for (int i = 1; i <= 7; i ++)
for (int j = 1; j <= 7; j ++)
if(e[i][j] && st[i] && st[j])
p[find(i)] = find(j);
int cnt = 0;
for (int i = 1; i <= 7; i ++)
if(st[i] && p[i] == i)
cnt ++;
if(cnt == 1) ans ++;
return;
}
st[u] = 1;// 打开第 u 个二极管
dfs(u + 1);
st[u] = 0;// 关闭第 u 个二极管
dfs(u + 1);
}
int main(){
//freopen("/config/workspace/test/test","r",stdin);
e[1][2] = e[1][6] = 1;
e[2][1] = e[2][7] = e[2][3] = 1;
e[3][2] = e[3][7] = e[3][4] = 1;
e[4][3] = e[4][5] = 1;
e[5][4] = e[5][7] = e[5][6] = 1;
e[6][1] = e[6][7] = e[6][5] = 1;
e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
dfs(1);
cout << ans << endl;
return 0;
}
问题 F: 【蓝桥杯2020初赛】平面切分
思路:在同一个平面内,如果添加一条直线,与平面所有的直线不相交,则会增加一个平面,如果与这个平面内的一条直线相交并且产生新的交点,那么就会额外增加一个平面。(也就是说,只要增加一条直线,必然多一个平面,若还与其他直线有n个交点,则会再多出n个平面)
那么我们只需对输入的每一条直线,判断是否是重边,计算当前直线与已有直线有多少个不同的交点,计算交点我们可以用set(自动去重)。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
typedef pair<double, double> PDD;
bool side[N]; //用来标记重边,防止重复计算交点
double a[N][2];//记录所有输入的边
int main(){
int n;
cin >> n;
int ans = 1; //初始平面数为1
for(int i=1;i<=n;i++){
cin >> a[i][0] >> a[i][1];
set<PDD> point; // 计算该直线与平面内的直线的不同交点的个数
for(int j=1;j<=i-1;j++){//查找重边
if(side[j]) continue;//已有相同直线
if(a[i][0] == a[j][0]){
if(a[i][1] == a[j][1]){//相同直线
side[i] = true;
break;
}
else continue;//斜率相同,平行,不用算交点
}
//相交直线计算交点
double x = (a[i][1] - a[j][1]) / (a[j][0] - a[i][0]);
double y = a[i][0] * x + a[i][1];
point.insert({x, y});
}
if(!side[i]) ans += point.size() + 1;
}
cout << ans << endl;
return 0;
}
问题 G: 回到学校
思路:用数组接a[n]收输入信息,再将其下标(学号)与值(进入次序)颠倒存入另一数组b[n]中,此时新数组即为按照进教室先后顺序排好的序列,输出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int n;
cin>>n;
int a[n+1];
for(int i=1;i<=n;i++){
cin>>a[i];
}
int b[n+1];
for(int i=1;i<=n;i++){
b[a[i]]=i;
}
for(int i=1;i<=n;i++){
cout<<b[i]<<' ';
}
return 0;
}
问题 H: 九九乘法表(教师版)
思路:数组记录所有九九乘法表出现的数,对输入的数循环比对即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int nn[50];
int loc=0;
for(int i=1;i<=9;i++){//直接把九九乘法表出现的所有数记录下来
for(int j=1;j<=i;j++){
nn[loc]=i*j;
loc++;
}
}
//cout<<loc<<endl; //loc为45,所以数组开50就够
int n;
cin>>n;
for(int i=0;i<loc;i++){
if(n==nn[i]){
cout<<"Yes"<<endl;
return 0;
}
}
cout<<"No"<<endl;
return 0;
}
问题 I: 逃命双曲线
思路:遍历x求y,y是整数时,计算所需时间,即x+y-2,取其中最小的。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
long long k;
cin>>k;
long long xk=sqrt(k)+1;
long long dmin=1000000000000;//亲身试错:INT_MAX太小了不够用
for(long long x=1;x<=xk;x++){
double y=(k*1.0)/(x*1.0);
double temp=y;
if(temp==(long long)y){
if(x+y-2<dmin){
dmin=x+y-2;
}
}
}
cout<<dmin<<endl;
return 0;
}
问题 J: Dongdziz与300刀1刀999
思路:原字符ASCII码加n后,比'A'多出的部分对26取模,得到的数加上'A',利用putchar()输出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
int n;
cin>>n;
string s;
cin>>s;
for(int i=0;i<s.length();i++){
int temp=(s[i]+n-'A')%26+'A';
putchar(temp);
}
return 0;
}
问题 K: Bob和Alice(4)
思路:多次尝试之后发现,将1到n的顺序排序左移1位后得到的Mi相加值最大,而此时计算出来的Mi=i(除了i==n时,因为最大那个数对1取模为0,相当于喂狗了)。所以输入为n时,答案应为1到n-1的和。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("/config/workspace/test/test","r",stdin);
long long n;
cin>>n;
long long sum=0;
for(int i=1;i<n;i++){
sum+=i;
}
cout<<sum<<endl;
return 0;
}