问题 A: 3-9 So Easy
题目描述
G先生发明了一个新游戏,游戏规则如下。 首先,他有一个nxn的矩阵,所有的元素一开始都是0.然后,他继续执行一些操作:每次选择一行或者一列,并向所选行或列中的所有元素添加一个任意的正整数。当所有操作完成后,他在矩阵中隐藏一个元素,这个元素被修改为-1,现在给出最后一个矩阵,要求你在最后一个隐藏操作之前找出隐藏元素。
输入
一个整数,即隐藏元素。
样例输入
3
1 2 1
0 -1 0
0 1 0
样例输出
1
思路
观察包括-1的矩阵正方形,对角线元素相加之和互相相等,根据此特性以及当x,y为边界时的特殊情况即可解决
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1005][1005];
signed main()
{
int n;
cin>>n;
int x,y;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
if(a[i][j]==-1)
{
x=i;
y=j;
}
}
}
int ans=0;
if(x>0&&y>0)
ans=a[x][y-1]+a[x-1][y]-a[x-1][y-1];
else if(x==0&&y!=0)
ans=a[x][y-1]+a[x+1][y]-a[x+1][y-1];
else
ans=a[x+1][y]+a[x][y+1]-a[x+1][y+1];
cout<<ans<<endl;
}
问题 B: 用递归的方法求值
题目描述
求1+2+3+4+5+...+n的值 。
输入
一个n(n不大于10000)
输出
输出1到n的累加和
样例输入
1
样例输出
3
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1005][1005];
int fff(int n)
{
if(n==1)
return 1;
return fff(n-1)+n;
}
signed main()
{
int n;
cin>>n;
cout<<fff(n)<<endl;
}
问题 C: 字符串移位包含问题
题目描述
对于一个字符串来说,定义一次循环移位操作为:将字符串的第一个字符移动到末尾,形成新的字符串。
给定两个字符串s1和s2,要求判定其中一个字符串是否是另一个字符串通过若干次循环移位后的新字符串的子串,例如CDAA是由AABCD两次以为后产生的新船BCDAA的字串,而ABCD与ABCD则不能通过多西移位使得其中一个字符串是新串的子串。
输入
一行,包含两个字符串,中间由单个空格隔开。字符串只包含字母和数字,长度不超过30.
输出
如果一个字符串是另一个字符串通过若干次移位产生的新串的子串,则输出true,否则输出false
样例输入
AABCD CDAA
样例输出
true
思路
将原字符串加在后面,从头向后遍历寻找是否有与给定子串相同的子串。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int m=1000000007;
int a[1005][1005];
signed main()
{
string s1;
string s2;
cin>>s1>>s2;
s1+=s1;
int i=0;
int j=0;
while(i<s1.size()&&j<s2.size())
{
if(s1[i]==s2[j])
{
i++;
j++;
}
else
{
i=i-j+1;
j=0;
}
}
if(j>=s2.size())
cout<<"true"<<endl;
else cout<<"false"<<endl;
}
问题 D: LELE的RPG难题
题目描述
人称"AC女之杀手"的超级偶像 LELE最近忽然玩起了深沉,这可急坏了众多Cole(LELE 的粉丝,即"可乐"),经过多方打探,某资深 Cole终于知道了原因,原来,LELE最近研究起了著名的RPG难题。有排成一行的n个方格,用红(Red)、粉(Pink)和绿(Green)三色涂每个格子,每格涂一个颜色,要求任何相邻的方格不能同色,且首尾两格也不同色,求全部的满足要求的涂法。以上就是著名的RPG难题。如果你是 Cole,我想你一定会想尽办法帮助LELE解决这个问题的;如果不是,那么看在众多漂亮的痛不欲生的Cole 的面子上,你也不会袖手旁观吧?
输入
输入数据包含多个测试样例,每个测试样例占一行,由一个整数n组成(0<n≤50)
输出
对于每个测试样例,请输出全部的满足要求的涂法,每个样例的输出占一行。
样例输入
1
3
样例输出
3
6
思路
本题采用递推的思想。
除了1,2,3的值是3,6,6以外,其他的都符合dp[i] = dp[i-1]+2*dp[i-2]。
共有两种情况:
1:第i-1个方格和第一个方格颜色相同,则第i-2个方格和第i-1个方格颜色不同,即与第一个方格颜色不同,此时第i个格子可以涂两种颜色,方案数为2*dp[i-2]。
2:第i-1个方格和第一个方格颜色不同,此时第i个格子只能涂一种颜色,方案数为1*dp[i-1]
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int n;
while(cin>>n)
{
int dp[55];
dp[1]=3;
dp[2]=6;
dp[3]=6;
for(int i=4;i<=n;i++)
{
dp[i]=dp[i-1]+2*dp[i-2];
}
cout<<dp[n]<<endl;
}
}
问题 E: 同行列对角线的格
题目描述
输入三个自然数N,i,j(1≤i≤n,1≤j≤n),输出在一个N*N格的棋盘中(行列均从1开始编号),与格子(i,j)同行、同列、同一对角线的所有格子的位置。
如:n=4,i=2,j=3表示了棋盘中的第二行第三列的格子,
当n=4,i=2,j=3时,输出的结果是:
(2,1) (2,2) (2,3) (2,4) 同一行上格子的位置
(1,3) (2,3) (3,3) (4,3) 同一列上格子的位置
(1,2) (2,3) (3,4) 左上到右下对角线上的格子的位置
(4,1) (3,2) (2,3) (1,4) 左下到右上对角线上的格子的位置
输入
一行,三个自然数N,i,j,相邻两个数之间用单个空格隔开(1≤N≤10)。
输出
第一行:从左到右输出同一行格子位置;
第二行:从上到下输出同一列格子位置;
第三行:从左上到右下输出同一对角线格子位置;
第四行:从左下到右上输出同一对角线格子位置。
其中每个格子位置用如下格式输出:(x,y),x为行号,y为列号,采用英文标点,中间无空格。相邻两个格子位置之间用单个空格隔开
样例输入
4 3 2
样例输出
(2,1) (2,2) (2,3) (2,4)
(1,3) (2,3) (3,3) (4,3)
(1,2) (2,3) (3,4)
(4,1) (3,2) (2,3) (1,4)
思路
找规律,直接输出
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int n,x,y;
cin>>n>>x>>y;
for(int i=1;i<=n;i++)
{
if(i==x)
{
for(int j=1;j<=n;j++)
{
cout<<"("<<x<<","<<j<<")"<<" ";
}
cout<<endl;
}
}
for(int i=1;i<=n;i++)
{
if(i==y)
{
for(int j=1;j<=n;j++)
{
cout<<"("<<j<<","<<y<<")"<<" ";
}
cout<<endl;
}
}
for(int i=1;i<=n;i++)
{
if((y-x+i)>=1&&(y-x+i)<=n)
cout<<"("<<i<<","<<y-x+i<<")"<<" ";
}
cout<<endl;
for(int i=1;i<=n;i++)
{
if((y-i+x)>=1&&(y-i+x)<=n)
cout<<"("<<y-i+x<<","<<i<<")"<<" ";
}
cout<<endl;
}
问题 F: 基因相关性
题目描述
为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的DNA进行比对,以判断该比对的DNA是否具有相关性。
现比对两条长度相同的DNA序列。定义两条DNA序列相同位置的碱基为一个碱基对,如果一个碱基对中的两个碱基相同的话,则称为相同碱基对。接着计算相同碱基对占总碱基对数量的比例,如果该比例大于等于给定阈值时则判定该两条DNA序列是相关的,否则不相关。
输入
有三行,第一行是用来判定出两条DNA序列是否相关的阈值,随后2行是两条DNA序列(长度不大于500)。
输出
若两条DNA序列相关,则输出“yes”,否则输出“no”。
样例输入
0.85
ATCGCCGTAAGTAACGGTTTTAAATAGGCC
ATCGCCGGAAGTAACGGTCTTAAATAGGCC
样例输出
yes
代码
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
char s1[501],s2[501];
int len;
double x,sum=0;
int i;
cin>>x>>s1>>s2;
len=strlen(s1);//计算字符串长度
for(i=1; i<=len; i++) //从头到尾枚举串1与串2是否相同
if(s1[i]==s2[i])
sum++;//统计相同个数
if(sum/len>=x)//所占比例大于所给阀值
cout<<"yes"<<endl;//相关
else//否则
cout<<"no"<<endl;//不相关
return 0;
}
问题 G: 【蓝桥杯2020初赛】七段码
数数(😥)
问题 H: 【蓝桥杯2020初赛】平面切分
【问题描述】
平面上有 N 条直线,其中第 i 条直线是 y = Ai · x + Bi。
请计算这些直线将平面分成了几个部分。
【输入格式】
第一行包含一个整数 N。
以下 N 行,每行包含两个整数 Ai; Bi。
【输出格式】
一个整数代表答案。
【样例输入】
3
1 1
2 2
3 3
1
2
3
4
【样例输出】
6
1
思思路
s在同一个平面内,如果添加的每一条直线互不相交,则每添加一条直线,就会增加一个平面;当添加一条直线时,这条直线与当前平面内已有直线每产生一个不同位置的交点时,这条直线对平面总数量的贡献会额外增多一个,利用set容器中不允许两个元素有相同的键值,在set中每个元素的值都唯一。
代代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
int ans;
bool st[1010];
pair<long double,long double> p;
long double s[1010][2];
signed main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i][0]>>s[i][1];
set<pair<long double,long double>> points;
for(int j=0;j<i;j++)//以此比较重边,以及依次算出交点
{
if(st[j])
continue;
if(s[i][0]==s[j][0])
{
if(s[i][1]==s[j][1])
{
st[i]=true;
break;
}
else continue;
}
p.first=(s[j][1]-s[i][1])/(s[i][0]-s[j][0]);
p.second=s[i][0]*p.first+s[i][1];
points.insert(p);//set内键值对不可重复
}
if(!st[i])
ans+=points.size()+1;
}
cout<<ans+1;
}
问题 J: 两只大熊猫
题目描述
有2000001只大熊猫被放置在一排,坐标从-1000000到1000000,
然后这其中有K只连续的大熊猫其实是Zheng的兄弟姐妹们假扮的。
并且我们知道坐标X的大熊猫一定是被假扮的。
T想你告诉他,所有有可能被假扮的大熊猫的坐标
举个例子吧,如果K=3,X=7
那么5 6 7 8 9这5个位置都有可能是Zheng的兄弟姐妹们假扮的
速速告诉T,那么T就能把Zheng抓出来暴打一顿
输入
(1<=K<=100)
(0<=X<=100)
输出
样例输入
3 7
样例输出
5 6 7 8 9
代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
signed main()
{
int k,x;
cin>>k>>x;
for(int i=x-k+1;i<=x+k-1;i++)
cout<<i<<" ";
}
问题 K: 自摸
题目描述
小L刚睡醒,就被他的狐朋狗友拖去打麻将。
要知道,赌博是不对的!所以他们以点数记输赢。
他们每一个人初始时都有k点,然后又因为这n个人都是三脚猫,只会自摸(每一把都保证有一个人能赢),也就是说,每一把除去赢家,所有人都会从自身点数中扣去一点,但是,赢家是不会加点的。
那么q把下来,由你来判断这n个玩家是否手上还留有点数。
输入
输入的第一行为3个正整数,n,k,q,随后跟着q行,每行一个正整数。
含义为:n个人,每个人初始点数为k,一共玩q轮,每轮第a[i]个人赢。
1≤�≤105
1≤�≤109
1≤�≤105
1≤��≤�
输出
输出n行,如果第i 个人还有剩余(点数大于0),则第i行输出"Yes",否则输出"No"
样例输入
6 3 4
3
1
3
2
样例输出
No
No
Yes
No
No
No
思路:正常每一次都遍历会时间超限,记录每一次赢的人a[i]=a[i]+1,若最后a[i]<=q-k,则输出No,反之yes
代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
signed main()
{
int n,k,q;
cin>>n>>k>>q;
int a[100005]={0};
int res;
int qq=q;
while(q--)
{
cin>>res;
a[res]=a[res]+1;
}
for(int i=1;i<=n;i++)
{
if(a[i]<=(qq-k))
cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
}
问题 L: 一起去看海
题目描述
“某对”准备去海边玩。
景区门票对身高小于xx的小朋友免费。景区管理人员想请程序员先生写一个程序,来统计收费游客的个数。
输入
第一行包含空格隔开的两个正整数 N NN 和 K KK ,分别代表“游客的总人数”和“开始收费身高”。
第二行包含 N NN 个空格隔开的正整数 h 1 , h 2 , . . . , h N h_1, h_2, ..., h_Nh1,h2,...,hN,分别代表这 N NN 位旅客的身高。
数据范围:
- 1 ≤ N ≤ 1 0 5 1leq Nleq 10^51≤N≤105
- 1 ≤ K ≤ 500 1leq Kleq 5001≤K≤500
- 1 ≤ h i ≤ 500 1leq h_ileq 5001≤hi≤500
输出
输出一行一个正整数,代表身高不低于 K KK 的游客的个数。
样例输入
4 150
150 140 100 200
样例输出
2
代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
signed main()
{
int n,k;
cin>>n>>k;
int h;
int ans=0;
while(n--)
{
cin>>h;
if(h>=k)
ans++;
}
cout<<ans<<endl;
}
问题 P: 山 or 水库 ?
题目描述
有N座山围成一圈(N为奇数),从1到N标号。约定0指 N ,N + 1指1。
第i和第i + 1座山之间有一座水库,标号为i。
当第i座山下2x个单位雨时,第i和第i − 1座水库就能收到x单位水。
给定每个水库收到的水量Ai
求每座山的雨量。
输入
N
A1 A2 A3 ..... An
3 <= N <= 1e5 - 1
N保证是奇数
0 <= Ai <= 1e9
输出
打印N个整数,表示山1,山2,…,山N的雨量
样例输入 复制
3
2 2 4
样例输出 复制
4 0 4
思路
2*w[1]=s[1]+s[2]
2*w[2]=s[2]+s[3]
2*w[3]=s[3]+s[4]
···可以发现,等式右边奇数项全部相加为s[1]+Σs[i](1<=i<=n),偶数项全部相加等于Σs[i](2<=i<=n),所以我们通过w[i],可以得出s[1]的值,分别代入方程可以则可得到s[i]。
代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
signed main()
{
int n;
cin>>n;
int s[100005];
int w[100005];
for(int i=1;i<=n;i++)
cin>>w[i];
int ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
if(i%2==1)
ans1+=2*w[i];
else ans2+=2*w[i];
}
s[1]=(ans1-ans2)/2;
for(int i=2;i<=n;i++)
{
s[i]=2*w[i-1]-s[i-1];
}
for(int i=1;i<=n;i++)
cout<<s[i]<<" ";
}
问题 I: 我的世界
题目描述
小T在我的世界中建立了N 根柱子,其中第i根柱子由Hi个方块组成。
对一次操作的定义是:去掉某根柱子的一个方块
小T对一根柱子最多进行一次操作,问能否找到一种方法,使得N根柱子从左到右含有的方块数量非递减
例如本来有5根柱子,高度分别是1 、2、1、1、3
可以选择对第二根柱子进行一次操作(减少第二根柱子中的一个方块)
之后所有柱子所包含的方块数为1,1,1,1,3非递减。
输入描述
输入包括2 行
第一行是1 个整数N ,代表我的世界中共有N 根柱子
第二行是N 个空格隔开的正整数H i,能否找到一种方法,在对一根柱子顶多操作一次的前提下,使得这N 根柱子所包含的方块数量非递减。
如果可以,输出YES,否则输出No
输入
4
1 3 2 1
输出
No
思路
每个柱子都有一定的方块数,要想让柱子从左到右方块数一次增加,就需要从左到右,在这个柱子的方块数不少于前一个的前提下,使得这个柱子的方块数量尽可能地少。(通俗地说,就是使左边柱子的方块数量尽可能少首先左边第一个柱子,方块数越少越好,因此第一个柱子就直接进行一次操作之后从第二个柱子开始向右遍历所有的柱子,遍历到这个柱子时,如果这个柱子方块儿仍比前一个少,就直接No(前面一个柱子的方块数已经达到最小值)。否则,如果这个柱子的方块比上一个多,就可以减少一个(减少后仍不少于前一个柱子但如果这个柱子的方块数量和上一个已经一样多了,那么这个柱子就不能再减少方块数量了。
如果遍历到最后也没有输出No,就输出Yes即可。
代码
#include<bits/stdc++.h>
#include<string.h>
#include<set>
#define int long long
using namespace std;
signed main()
{
int n;
cin>>n;
int a[100005];
for(int i=0;i<n;i++)
cin>>a[i];
a[0]=a[0]-1;
for(int i=1;i<n;i++)
{
if(a[i]<a[i-1])
{
cout<<"No"<<endl;
return 0;
}
else if(a[i]>a[i-1])
a[i]=a[i]-1;
}
cout<<"Yes"<<endl;
}