蓝桥杯练习系统算法训练 贫穷的城市

问题描述

        某城市有n个小镇,编号是1~n。由于贫穷和缺乏城市规划的人才,每个小镇有且仅有一段单向的公路通往别的小镇。有一天,一辆小轿车误入了这座城市,它只能沿着公路走,它走啊走,却再也走不出这座城市了……问如果这辆车从某个小镇出发,走了若干段公路,会到达哪个小镇。每组数据有m个询问。

输入格式

       第一行两个数n、m:表示小镇数和询问数;
  接下来一行n个数,第i个数Ai:表示从小镇i出发的公路会通向小镇Ai;
  接下来m行,第i行有两个数Bi和Ci:询问小轿车从小镇Bi出发,走过Ci段路后会达到哪个小镇。

输出格式

  一行m个数回答每个询问。

样例输入

3 3
2 1 3
1 1
2 2
3 3

样例输出

2 2 3

数据规模和约定

  对于60%的数据:1<=n、m<=1000,1<=Ai、Bi<=n,0<=Ci<=1000;
  对于100%的数据:1<=n、m<=100000,1<=Ai、Bi<=n,0<=Ci<=100000。

解题思路:

        这道题是一道经典的利用倍增思想的题,用暴力的话只能拿到60%的测试点,剩下的会运行超时。

        那么,什么是倍增法呢?倍增法就是利用任何一个数都能用2的n次方表示,例如13的二进制为1101,那么13就可以用2的3次方+2的2次方+2的0次方表示。所以我们只需要先预处理一下数据,求得每个小镇跳2的n次方步会到达哪个小镇就可以啦。要计算从s小镇跳2的n次方步到哪里的公式为go[s][n]=go[go[s][n-1]][n-1]。

        等式的右边go[s][n-1]的含义为从s小镇跳2的n-1次方个区间到达的小镇,我们假设到达的小镇为t,所以go[go[s][n-1]][n-1]=go[t][n-1],表示从t小镇跳2的n-1次方达到的小镇,所以全部过程是先从s小镇跳2的n-1次方步到达t小镇,再从t小镇跳2的n-1次方步达到终点,总共跳了2的n-1次方+2的n-1次方步=2的n次方步。由于m<=100000,所以我们只需要计算到每个小镇跳最多2的17次方步就可以啦。

        倍增法只能用于静态的数据的预处理。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAX=100005;
int rode[MAX][19];
int n,m;
int main()
{
	int i,j;
	cin>>n>>m;
	for(i=1;i<=n;i++)	cin>>rode[i][0];
	for(i=1;i<18;i++)
	{
		for(j=1;j<=n;j++)
		{
			rode[j][i]=rode[rode[j][i-1]][i-1];//倍增重要公式 
		}
	}
	for(i=1;i<=m;i++)
	{
		int a,b,count=0;//count用来表示现在是n的几次方步了
		cin>>a>>b;
		while(b!=0)
		{
			if(b%2==1)	a=rode[a][count];//如果为1则需要跳步
			b/=2;
			count++;
		}
		cout<<a<<" ";
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值