NOIP模拟 开锁匠(找规律+有坑)

【题目描述】

经济危机席卷全球,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

 

对于40%的数据,直接暴力模拟即可,复杂度O(n*k);

对于60%的数据,可以知道每次出错次数为i与i+1位置差(如果为负就加上n),第一次需特殊考虑(因为不一定第一个就是最后一个),复杂度O(k);

对于100%的数据,可以知道经过n次后出错次数会进入循环,只用计算1次循环的总出错次数*(k/n)(第一次循环单独处理),最后加上第k%n次总出错次数即可。

贴代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=1e6+10;

struct num{
	ll s,id;
}a[MAXN];
ll dp[MAXN];

bool cmp(num a,num b)
{
	return a.s<b.s;
}

ll Read()
{
	ll i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void putll(ll x)
{
	if(x>9)
	  putll(x/10);
	putchar(x%10+48);
}

int main()
{
	ll n=Read(),k=Read();
	for(ll i=1;i<=n;++i)
	  a[i].s=Read(),a[i].id=i;
	sort(a+1,a+n+1,cmp);
	ll m=a[1].id-1;
	for(ll i=1;i<=n;++i)
	{
		ll r;
		if(i!=1)
		{
		    r=a[i].id-a[i-1].id;
		    if(r>=0)
		      dp[i]=dp[i-1]+r;
		    else
		      dp[i]=dp[i-1]+r+n;
		}
		else
		{
		    r=a[i].id-a[n].id;
		    if(r>=0)
		      dp[i]=r;
		    else
		      dp[i]=r+n;
		}
	}
	if(k<=n)
	{
		m+=dp[k]-dp[1];
		cout<<m<<endl;
	}
	else
	{
		ll ys=k%n;
		if(ys==0)
		{
			m+=dp[n]-dp[1];
			m+=dp[n]*(k/n-1);
		}
		else
		{
			m+=dp[n]-dp[1];
			m+=dp[n]*(k/n-1);
			m+=dp[k%n];
			cout<<m<<endl;
		}
	}
	return 0;
}

 

posted @ 2018-08-21 15:58  Ishtar~  阅读(263)  评论(0)    收藏  举报