描述
经济危机席卷全球,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
解析:
签到题,直接让我签到失败的签到题。。。
显然,最暴力的做法就是简单模拟。。。
然而,我们再仔细思考一下,错误的次数不就是手里这把钥匙与目标钥匙的环形距离吗?
再仔细思考一下,每
次不就是一个一模一样的循环了吗?
于是这道题就变得十分简单了。。。
当然,如果这么简单,也就不会让我签到失败了。。。
注意对第一扇门的特殊处理。。。
于是就在
上
了。。。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define st static
inline
ll getint(){
st ll num;
st char c;
for(c=gc();!isdigit(c);c=gc());
for(num=0;isdigit(c);c=gc())num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline
void outint(ll a){
st char ch[23];
if(!a)pc('0');
while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
while(ch[0])pc(ch[ch[0]--]);
}
int n,k;
int fir;
int pos[100005];
ll ans[100005];
int main(){
n=getint();
k=getint();
for(int re i=0;i<n;++i){
int key=getint();
pos[--key]=i;
if(i==0)fir=key;
}
ll Ans=(pos[0]-pos[fir]+n)%n;
for(int re i=1;i<=n;++i){
int pre=pos[(i-2+n)%n];
ll delta=(pos[i-1]-pre+n)%n;
ans[i]=ans[i-1]+delta;
}
Ans+=ans[n]*(k/n);
Ans+=ans[k%n]-ans[1];
outint(Ans);
return 0;
}