【2018/08/21】T1-模拟-开锁匠(SDOJ 3432)

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/81909452

开锁匠

描述

经济危机席卷全球,L国也收到冲击,大量人员失业。

然而,作为L国的风云人物,X找到了自己的新工作。从下周开始,X将成为一个酒店的助理锁匠,当然,他得先向部门领导展示他的开锁能力。

领导给了X一串钥匙,这串钥匙串在一个大圆环上,每把钥匙有一个编号(1..N)。然后蒙上X的眼睛并把他带到一个圆形的大房间中。在这个房间中有N个上锁的门,用1..N表示,这串N把钥匙每一把正好打开一扇门(钥匙编号和门编号一致就可以打开)。

X的工作就是打开每扇门。他因为蒙着眼睛,不过可以沿着房间的墙壁移动,不能改变方向,直到他摸着一扇门,然后他会尝试用第一把钥匙(最左边)来打开门,如果钥匙不能打开门,他会将钥匙移到另外一侧(最右边),重复这样直到找到正确的钥匙,当他把所有门打开就结束任务。不过X不知道的是,领导并不是测试 他开锁能力,而是测试他的耐心,所以领导故意把X带到圆形房间,这样X每开一扇门后,领导就会在后面悄悄把门再次锁上,这样以来,X打开最后一扇门后又回到第一扇门然后一直重复下去。不过X是一个勤奋和耐心的人,他一直毫无怨言的做着这件事,不说任何抱怨的话,只是在每开一扇门他会默默的统计自己已经错误了多少次,不过慢慢时间太久他的计算能力不足,需要你来帮助他计算错误的次数。

任务:给定数字k,回答当X打开第k扇门时,一共错误了多少次?

输入

第一行是2个整数N,K

接下来N行,每行包含一个整数Vi,表示钥匙串从第一把(左侧)到最后一把,第i把钥匙的编号。

输出

一个整数,回答第k次打开一扇门,已经错误的次数

样例输入

4 6
4
2
1
3

样例输出

13

样例解释

打开第1扇门的尝试(1号门):4 2 1 3,错误2次,打开后钥匙排列:1 3 4 2

打开第2扇门的尝试(2号门):1 3 4 2,错误3次,打开后钥匙排列:2 1 3 4

打开第3扇门的尝试(3号门):2 1 3 4,错误2次,打开后钥匙排列:3 4 2 1

打开第4扇门的尝试(4号门):3 4 2 1,错误1次,打开后钥匙排列:4 2 1 3

打开第5扇门的尝试(1号门):4 2 1 3,错误2次,打开后钥匙排列:1 3 4 2

打开第6扇门的尝试(2号门):1 3 4 2,错误3次,打开后钥匙排列:2 1 3 4

总错误13次

数据规模

40%数据:1<=N,K<=1000

另外60%数据:1<=K<=50000

100%数据:1<=N<=100000,1<=Vi<=N,1<=K<=10^9

分析

很简单的一道题啊,我居然没想出来,oh god,退役退役~

我们仔细看一下样例解释,发现如果要开第 i 号门,则钥匙串的开头一定是第 i - 1号门对应的钥匙,1号门除外,开这号门的时候钥匙串的第一个应该是第 n 号钥匙,那我们记录一下在一开始给出的钥匙串里,每一个钥匙的位置,然后开第 i 号门的时候错误次数就是pos[i] - pos[i-1],如果 pos[i] - pos[i-1] < 0 ,我们就将其加上 n 即可,手动推一下就出来了,因此我们可以O(1)求出每开一次门的错误次数,而后我们又发现这就是一个圈,是重复的(看样例解释),然后乱搞一下就出来了,看代码

代码

代码写的丑,大家意会

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<queue>
#define N 100009
#define M 405003
#define inf 0x7fffffff
#define in read()
#define ll long long
using namespace std;
int n,k,key[N],pos[N];
int main(){
	scanf("%d%d",&n,&k);
	ll i,j;
	for(i=1;i<=n;++i){
		scanf("%d",&key[i]);
		pos[key[i]]=i;
	}
	ll ans=pos[1]-1,err=0;//第一次的时候一号门的错误次数要特判
	if(k<=n){
		for(i=2;i<=k;++i){
			ll hh=pos[i]-pos[i-1];
			if(hh<0) hh+=n;
			ans+=hh;
		}
		printf("%lld",ans);
	}
	else{
		for(i=2;i<=n;++i){
			ll hh=pos[i]-pos[i-1];
			if(hh<0) hh+=n;
			err+=hh;
		}
		j=pos[1]-pos[n];
		if(j<0) j+=n;
		err+=j;//循环是从2~n 加上1,组成的,此时err中保存了一组循环里错误次数
		ll num=k/n;
		ans+=err*1ll*num;
		int h=k%n;
		if(h==0) ans-=j;
		for(i=2;i<=h;++i){
			ll hh=pos[i]-pos[i-1];
			if(hh<0) hh+=n;
			ans+=hh;
		}
		printf("%lld",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/81909452