今天还是给大家分享几道题目,希望大家可以好好理解。
第一题
问题描述
小蓝有一天误入了一个混境之地。
好消息是:他误打误撞拿到了一张地图,并从中获取到以下信息:
- 混境之地是一个 n⋅m大小的矩阵,这个地图中一共有四种磁场,记为
A
,B
,C
,D
。 - 他现在所在位置的坐标为 (x1,y1)而这个混境之地出口的坐标为 (x2,y2) 。
坏消息是:
- 当你站在磁场为
A
的方块上时,你下一步只能走到磁场为B
的方块上。 - 当你站在磁场为
B
的方块上时,你下一步只能走到磁场为C
的方块上。 - 当你站在磁场为
C
的方块上时,你下一步只能走到磁场为D
的方块上。 - 当你站在磁场为
D
的方块上时,你下一步只能走到磁场为A
的方块上。
小蓝可以往上下左右四个方向行走。
小蓝想知道他能否逃离这个混境之地,如果可以逃离这里,输出 Yes
,反之输出 No
。
输入格式
第一行输入两个正整数 n,m表示矩阵的大小。
第二行输入四个正整数 x1,y1,x2,y2,表示小蓝当前所在位置的坐标,以及混境之地出口的坐标。
接下来 n 行 m列为混境之地的矩阵,其中 A
,B
,C
,D
代表不同磁场,仅包含 A
,B
,C
,D
四种字符。
输出格式
输出数据共一行一个字符串:
- 若小蓝可以逃离混境之地,则输出
Yes
。 - 若小蓝无法逃离混境之地,则输出
No
。
输入案例:
5 5
1 1 5 5
ABCDA
ABCDB
ABCDC
ABCDD
ABCDA
输出案例:
Yes
代码部分:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1e3+10;
bool vis[N][N];
char c[N][N];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
ll n,m,sx,sy,fx,fy;
bool check(ll x,ll y,ll nx,ll ny){if(c[x][y]=='A'&&c[nx][ny]=='B')return true;if(c[x][y]=='B'&&c[nx][ny]=='C')return true;if(c[x][y]=='C'&&c[nx][ny]=='D')return true;if(c[x][y]=='D'&&c[nx][ny]=='A')return true;else return false;
}
bool bfs(int x,int y){
if(x==fx&&y==fy)return true;
vis[x][y]=true;
for(int j=0;j<4;j++){int nx=x+dx[j];int ny=y+dy[j];if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny])continue;if(check(x,y,nx,ny)){if(bfs(nx,ny))return true;}
}
return false;
}
int main()
{cin>>n>>m>>sx>>sy>>fx>>fy;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>c[i][j];}}bool flag=bfs(sx,sy);if(flag==true)cout<<"Yes";else cout<<"No";return 0;
}
这是一道经典的bfs问题,是一道比较传统的bfs问题。
这道题要注意调用bfs过程中返回true,来终止递归,要理解出口的意思。
第二题:
问题描述
小蓝现在有一个长度为 n仅由小写字母组成的的字符串 s ,小蓝可以对字符串进行任意次操作,每次操作小蓝可以选择一个整数 i ,其中 i∈[1,n−1] ,然后选择如下两种操作之一:
- 将 si变为其字典序加一的小写字母,si+1 变为其字典序减一的小写字母。
- 将 si 变为其字典序减一的小写字母,si+1变为其字典序加一的小写字母。
小蓝想知道通过操作 s可以变成的最小字典序字符串是什么,但是小蓝不擅长字符串问题,请你帮小蓝解决这个问题。
注意:操作过程中要保证 s始终是由小写字母组成的字符串。
输入格式
第一行输入一个整数,代表 n 。
第二行输入一个长度为 n仅由小写字母构成的字符串,代表 s 。
输出格式
输出一行一个字符串,代表 s 可以变成的字典序最小的字符串。
输入案例:
2
cb
输出案例:
ad
代码部分:
#include <bits/stdc++.h>
using namespace std;
string s;
int n;
long long sum;
int main()
{cin>>n>>s;for(int i=0;i<n;i++){sum+=s[i]-'a';s[i]='a';}for(int i=n-1;i>=0;i--){if(sum>=25){s[i]='z';sum-=25;}else{s[i]='a'+sum;sum=0;}}cout<<s;return 0;
}
注意这类题目有一个特点就是可以将数组中的或者字符串中的内容变成同一个数,然后统计变化量,再根据题意来做后面处理。
第三题:
问题描述
小蓝面临一个数学问题:给定一个整数 S,他需要构造出一个长度为 n 的序列,其中每个数都在 [l,r]范围内,并且整个序列的和值为 S。
当然,这样的结果会有很多,小蓝希望你帮助他构造出字典序最小的满足条件的序列。
输入格式
输入包含四个整数 S、n、l和 r,分别表示目标和值,序列的长度,以及每个数的取值范围。
输出格式
输出一个长度为 n 的序列,每两个数之间用空格分隔,如果无法构造,输出 −1。
输入案例:
10 3 2 5
输出案例:
2 3 5
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int main()
{vector<int>num(N);long long s,n,l,r;cin>>s>>n>>l>>r;if(n*r<s||n*l>s){cout<<-1;return 0;}for(int i=0;i<n;i++){num[i]=l;}int sum=s-n*l;for(int i=n-1;i>=0;i--){if(sum>=r-l){num[i]=r;sum=sum-r+l;}else{num[i]=l+sum;break;}}for (int i = 0; i < n; i++) {if (i > 0) {cout << " ";}cout << num[i];}return 0;
}
这道题和第二题是类似的,思路相同。
第四题:
题目背景
在一个神奇的魔法世界中,有一座古老的迷幻之城。迷幻之城被分成 n 个岛屿,编号从 1 到 n,共有 m 座桥。迷幻之城的居民们希望能够建立起紧密的联系,每个岛屿上的居民都想知道自己最多能到达多少个岛屿。
请你编写程序解决这个问题。
输入格式
第一行包含两个整数 n和 mm(1≤n≤105,0≤m≤min105,2n(n−1)),表示岛屿的数量和桥的数量。
接下来 m行,每行包含两个整数 ui,vi (1≤ui,vi≤n),表示编号为 ui和 vi 的岛屿之间有一座桥。
输出格式
输出一行包含 n个以空格分隔的整数,第 i 个整数表示编号为 i的岛屿上的居民最多能到达的岛屿个数。
代码部分:
#include <bits/stdc++.h>
using namespace std;
int a[100005],pre[100005],siz[100005],n,m;void init(){for(int i=1;i<=n;++i)pre[i]=i,siz[i]=1;
}int root(int x){return pre[x]==x?x:root(pre[x]);
}void merge(int x, int y)
{int rx = root(x), ry = root(y);if(rx == ry)return;//已经连通,无需处理//如果rx更大,则交换,可以保证siz[rx] <= siz[ry]if(siz[rx] > siz[ry])swap(rx, ry);//此时有siz[rx] <= siz[ry],所以一定是rx -> rypre[rx] = ry;siz[ry] += siz[rx];//操作完成后rx将不再作为根,于是它的siz也没有意义了,也不会再变化了
}int main()
{cin>>n>>m;init();for(int i=1;i<=m;++i){int x,y;cin>>x>>y;merge(x,y);}for(int i=1;i<=n;i++){cout<<siz[root(i)]<<" ";}return 0;
}
这道题用的是合并集的思想,这种问题是模版问题,大家可以看看理解理解。
第五题:
问题描述
在接下来的 N天里(编号从1到 N),坤坤计划烹饪披萨或西兰花。他写下了一个长度为 N 的字符串 A,对于每个有效的 i,如果字符 Ai 是 '1',那么他将在第 ii 天做披萨,如果 Ai是 '0',他将在这一天做西兰花。
坤坤的儿子小沸,就像大多数孩子一样,喜欢披萨但讨厌西兰花。他想选择一个 A 的长度为 K 的子串,并将这个子串中的每个字符 '0' 改为 '1'。然后,让我们定义披萨时间为坤坤连续做披萨的最大天数。请找出小沸可以达到的最大披萨时间。
输入格式
第一行包含两个用空格分隔的整数 N和 K(1≤K≤N≤103)。
第二行包含一个长度为 N的只包含 0
和 1
的字符串 A。
输出格式
打印一行,其中包含一个整数——最大的披萨时间。
输入案例:
13 2
0101110000101
输出案例:
5
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int prefix[N],suff[N];
char s[N];
int ans;
int main()
{int n,k;cin>>n>>k;for(int i=0;i<n;i++)cin>>s+1;for(int i=1;i<=n;i++){if(s[i]=='0')prefix[i]=0;else{prefix[i]=prefix[i-1]+1;}}for(int i=n;i>=1;i--){if(s[i]=='0')suff[i]=0;else{suff[i]=suff[i+1]+1;}}for(int i=k;i<=n;i++){int j=i-k+1;ans=max(ans,k+prefix[j-1]+suff[i+1]);}cout<<ans;return 0;
}
这道题巧妙用了前缀和以及后缀和的思想,对于这个问题大家要注意题目一般会要求让你求解某一段连续数字,然后可以更改某一部分的值。这类问题可以以更改部分的长度为两端点,然后向两端延伸。
第六题:
问题描述
依依有个长度为 n的序列 a,下标从 1开始。
她有 m次查询操作,每次她会查询下标区间在 [li,ri] 的 a中元素和。她想知道你可以重新排序序列 a,使得这 m次查询的总和最小。
求你求出 mm 次查询总和的最小值。
输入格式
第一行输入两个整数 n,m(1≤n,m≤105),表示序列 a 的长度以及查询次数。
第二行输入 n个整数 ai(1≤ai≤105),表示序列 a 中的元素。
接下来 m行,每行输入两个整数 li,ri(1≤li≤ri≤n),表示询问的下标区间。
输出格式
输出仅一行,包含一个整数,表示 m 次查询总和的最小值。
输入案例:
3 2
1 2 3
1 2
2 3
输出案例:
7
代码部分:
#include <bits/stdc++.h>
using namespace std;
long long sum;
const int N=1e5+10;
int a[N],diff[N],cnt[N];
int main()
{int n,m;cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+1+n);while(m--){int l,r;cin>>l>>r;diff[l]++;diff[r+1]--;}for(int i=1;i<=n;i++){cnt[i]=diff[i-1]+cnt[i-1];}sort(cnt+1,cnt+1+n,greater<int>());for(int i=1;i<=n;i++){sum+=a[i]*cnt[i];}cout<<sum;return 0;
}
这道题是前缀差的标准题目,大家可以记住这种题目的模版。统计某一区间数的个数,这一区间的长度发生变化,用数组来记录这个统计的个数。
第七题:
问题描述
小蓝现在有一个长度为 n仅由小写字母组成的的字符串 s ,小蓝可以对字符串进行任意次操作,每次操作小蓝可以选择一个整数 i,其中 i∈[1,n−1] ,然后选择如下两种操作之一:
- 将 si 变为其字典序加一的小写字母,si+1 变为其字典序减一的小写字母。
- 将 si变为其字典序减一的小写字母,si+1 变为其字典序加一的小写字母。
小蓝想知道通过操作, s最终可以变成多少种不同的字符串,但是小蓝不擅长计数问题,请你帮小蓝解决这个问题。
注意:操作过程中要保证 s始终是由小写字母组成的字符串。
输入格式
第一行输入一个整数,代表 n 。
第二行输入一个长度为 n仅由小写字母构成的字符串,代表 s 。
输出格式
输出一个数字,表示能够产生的字符串的种类数(结果对 1e9+7 取模)。
输入案例:
2
cb
输出案例:
4
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int sum,dp[202][5004];
int main() {int n;cin>>n;for(int i=1;i<=n;i++){char x;cin>>x;sum+=x-'a';}dp[0][0]=1;for(int i=1;i<=n;i++)for(int j=0;j<=sum;j++)for(int k=0;k<=min(j,25);k++)dp[i][j]=(dp[i][j]+dp[i-1][j-k])%MOD;cout<<dp[n][sum];return 0;
}
这道题难度其实很大的,发现很难解决,可以看看能不能用动态规划解决,前一部分对于后一部分的影响。
第八题:
问题描述
小蓝非常热爱数学,一天老师给小蓝出了一道数学题,想锻炼锻炼小蓝的思维能力。题目是这样的:给定两个数 a 和 b,在 a 到 b(包括 a,b)之间所有数的平方当中,试问有几个数能够表示为 x×y 的形式,其中 x 和 y 是质数。你能帮助小蓝一起来解决这个问题吗?
输入格式
第一行两个正整数 a,b,含义同题目所示。
输出格式
输出共一行,输出一个整数,代表那些能够表示为题目描述的形式的平方数的数量。
输入案例:
1 5
输出案例:
3
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int prime[N];
int ans;
void isprime(int n){for(int i=1;i<=n;i++)prime[i]=1;prime[0]=0;prime[1]=0;for(int i=2;i<=n;i++){for(int j=2*i;j<=n;j+=i){prime[j]=0;}}
}
int main()
{int a,b;cin>>a>>b;int x=1e5+5;isprime(x);for(int i=1;i<=x;i++){if(prime[i]&&i>=a&&i<=b)ans++;}cout<<ans;return 0;
}
这道题肯定有疑问,为什么说是要等于平方,但是只统计了一个质数的个数,这是因为对于一个完全平方数。
- 若
k² = p×q
(p, q
为质数),则k
本身必须是质数或 1。 - 证明:
设k² = p×q
,其中p ≤ q
为质数。- 若
k=1
,则1²=1×1
,但 1 不是质数,不成立。 - 若
k
是质数p
,则k² = p×p
(两个相同质数的乘积),成立。 - 若
k
是合数,设k = m×n
(m,n>1
),则k² = m²×n²
,此时m²
和n²
至少有一个不是质数(因平方数除 1 外非质数)。
- 若
好了,今天的分享就到这里,希望大家多多关注。