模拟题讲解

    Problem A 循环递增序列
题意:

小可的老师给她一个特殊的循环递增序列。这个序列由若干轮组成,每一轮的数字从1开始递增,并且每一轮的数字都会重复之前所有轮的数字。例如,第一轮只有1,第二轮为12,第三轮为123。以此类推。若干轮的数字形成了一个序列为:1 12123123412345…….

现在小可想知道这个序列中第 n 个数字是多少,你能帮助她解决这个问题吗?

 输入描述

输入一个正整数 n

 输出描述

输入这个循环递增序列中第 n 个数字是多少。

 输入样例
10
1.5 输出样例
4
1.6 数据描述

30%的数据下:1≤n≤10^{6}

100%的数据下:1≤n≤10^{14}

题解:

这道题中,第一层有一个数:1,第二层有两个数:1、2,第三层有三个数:1、2、3······以此类推,第n层就有n个数:1、2、3······n,所以我们可以定义一个变量x=1,当输入的n大于x时,n=n-x++,这是因为如果n的层数大于1时,就让n减去1这层的个数:1,如果n的层数大于2时,就让n减去2这层的个数:2,如果n的层数大于3时,就让n减去3这层的个数:3,以此类推,就得到了n=n-x++这个公式,也可以写成n-=x++,这样时间会快一点。

CODE:
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
int n;
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	long long n,x=1;
	cin>>n;
	while(n>x){
		n-=x++;
	}
	cout<<n<<"\n";
	return 0;
}
Problem B 密度最高的数字
题意:

小可最近对一种新定义的数字的密度很感兴趣。对于一个十进制数字 x,它的密度 ρ(x) 被定义为 x 的二进制数字中 1 的个数。小可发现,一个数字的大小并不一定意味着它的密度就大,她将这种现象称为“虚胖”。现在,她正在研究如何找到在给定区间 [l,r] 内密度最大的数字。如果在区间中存在多个密度相同的数字,她要求输出最小的那个。

你能帮助小可解决这个问题吗?

 输入描述

第一行:输入一个正整数 t ,表示询问组数。

接下来 t 行:每行输入两个正整数 l,r 表示要查询的区间。

 输出描述

对于每次查询,输出密度最大的数字。如果有多个答案,则输出最小的。

 输入样例
3
1 2
2 4
1 10
输出样例
1
3
7
 数据描述

20%的数据下:1≤t≤10^{2}​​,1≤l≤r≤10^{3}

100%的数据下:1≤t≤10^{4},1≤l≤r≤10^{18}

题解:

这个题中我们需要求在L和R区间区间内的一个十进制数转成二进制后1的数量最多的数,对于这个题,我们可以从L开始,将L转成二进制后,如果L的最后一位为零,改为1,判断此时的L是否超过R,如果没超过R,记录L中1的个数,然后继续判断,直到此时的L超过R为止,所以我们可以在输入每一组L和R后定义ans和sum,分别赋值为L和1,当(ans|sum)<=R时 ,令ans|=sum,然后sum<<=1;最后输出ans的值就可以了。

CODE:
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
int t;
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		long long l,r;
		cin>>l>>r;
		long long ans=l,sum=1;
		while((ans|sum)<=r){
			ans|=sum;
			sum<<=1;
		}
		cout<<ans<<"\n";
	}
	return 0;
}
Problem C 加一

题意:小可有一个数字n,她想要对数字n进行m次操作:每次操作,小可会将n的每一位上加一。例如,如果n是94,那么进行一次操作就会变成 105。

请你帮小可计算一下,进行m次操作后,n的长度是多少。

输入描述

第一行一个正整数t(1≤t≤2×10^{5}),代表有t组输入。

对于每组输入,有两个整数n(1≤n≤10^{9})和m(1≤m≤2×10^{5}​​),含义如题。

输出描述

对于每组输入,输出一开始的数字n进行m次操作后的长度是多少,这个结果模10^{9}+7输出。

样例输入

5
1912 1
5 6
999 1
88 2
12 100

样例输出

5
2
6
4
2115

提示

对于第一组输入,最后19121912变成了2102321023,长度为55。

对于第二组输入,最后55变成了2121,长度为22。

对于第三组输入,最后999999变成了101010101010,长度为66。

对于第四组输入,最后8888变成了10101010,长度为44。

题解:

如果仔细读一读题目的话,可以发现这是一道dp题,dp[i][j]中i表示当前数字,j表示进行操作的我们可以分两种情况,第一种,当i+j<10时,dp[i][j]=1,因为小于10时,这个数字是一个整体,所以赋值为1,第二种情况,当i+j>=10是,dp[i][j]=(dp[1][i-(10-j)]+dp[0][i-(10-j)])%mod,mod=1e9+7,因为当i+j不小于10是,有1和0组成,0为dp[0][i-(10-j)],1为dp[1][i-(10-j)],所以要把他们加起来,又因为题目中要取余10的9次方加7,所以要%mod,然后输入,当n不为零时,定义一个p=n%10,然后n=n/10,ans=(ans=dp[p][m])%mod,在内层循环外输出ans。

CODE:
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int mod=1e9+7;
const int n=200005;
long long f[n][10];
int main(){
	int t;
	scanf("%d",&t);
	for(int i=0;i<10;i++) {
		f[0][i]=1;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=9;j++){
			f[i][j-1]=f[i-1][j];
		}
		f[i][9]=(f[i-1][1]+f[i-1][0])%mod;
	} 
	while(t--){
		char s[20];
		int m,ans=0;
		scanf("%s %d",s,&m);
		int cd=strlen(s);
		for(int i=0;i<cd;i++){
			int sz=s[i]-'0';
			ans+=f[m][sz];
			ans%=mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}
Problem D 可达鸭棋
题意:

我们大家可能都玩过象棋、五子棋、围棋、飞行棋等,你有没有玩过可达鸭棋呢?

可达鸭棋有一个n × n大小的棋盘。棋盘上有一些魔法栅栏。坐标(x, y)代表棋子在第x行y列,左上角的坐标为(1, 1)。其中,小可的棋子在坐标为(Ax, Ay)的格子。只要不碰到魔法栅栏或者超出棋盘的范围,那么棋子可以沿着斜线走任意距离,也就是:

设当前棋子的坐标为(x,y),在不碰到魔法栅栏并且不超出棋盘的前提下,每一步棋子可以走到

(x + d, y + d) ,d可以取任意正整数。

(x + d, y−d) ,d可以取任意正整数。

(x−d, y + d) ,d可以取任意正整数。

(x−d, y−d) ,d可以取任意正整数。

注意:本题中,棋子不可以越过魔法栅栏移动,也不能吃掉魔法栅栏。小可想知道,一开始坐标为(Ax, Ay)的这个棋子,最少移动多少步能够到达坐标(Bx, By)。

注意:这里的多少步并不是经过了多少个格子。

输入描述

第一行一个正整数n(2≤n≤1500),代表棋盘的大小为n×n。

第二行是坐标(A​x​​,A​y​​),第三行是坐标(B​x​​,B​y​​)。

接下来是n×n的棋盘, .. 代表空白,可以走。 # 代表魔法栅栏。

保证起点和终点都是 . 。

输出描述

输出一个整数,如题。如果无法到达,输出−1−1。

样例输入1
5
1 3
3 5
....#
...#.
.....
.#...
#....
样例输出1
3
样例输入2
4
3 2
4 2
....
....
....
....
样例输出2
-1
样例输入3
18
18 1
1 18
..................
.####.............
.#..#..####.......
.####..#..#..####.
.#..#..###...#....
.#..#..#..#..#....
.......####..#....
.............####.
..................
..................
.####.............
....#..#..#.......
.####..#..#..####.
.#.....####..#....
.####.....#..####.
..........#..#..#.
.............####.
..................
样例输出3
9
提示

样例11的路径为:(1,3)→(2,2)→(4,4)→(3,5)(1,3)→(2,2)→(4,4)→(3,5),一共走了三步。

样例22无法从(3,2)(3,2)走到(4,2)(4,2)

题解:

这个题很明显是一道bfs广搜题,在主函数中我们需要输入加调用函数bfs,然后在bfs()中可以用手写队列或STL中的队列来进行bfs,我们还需要循环d的值,当到达终点时输出

这道题比较经典,所以就不放代码了,相信你们一定可以自己写出来的!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值