开锁

现在经济不景气,经济危机席卷城市,很多人丢失了工作(你会
发现,和题目完全没关系)。
然而,锴锴找到了一个新工作,一个五星级宾馆„„的锁匠„„
的助理„„现在,锁匠总管要测验锴锴的能力。
锁匠总管给了锴锴 N 把钥匙,它们在一个大的钥匙环上,锁匠总
管把锴锴带到了一个神奇的房间里,里面有 N 扇们,显然,N 把钥匙
每个能开一扇门。总管给锴锴的任务就是打开这些门。锴锴将门编号成 1 到 N,
钥匙环上的钥匙从左到右编号为 1 到 N,
锴锴开门顺序为 1、2、3„„N,到了一扇门前,锴锴用最左边的钥
匙去开门,没打开的话就把最左边的钥匙通过环转到最右边,继续重
复上述操作,直到打开门为止,打开后,锴锴便继续到下一扇门。锴
锴为了显示自己的与众不同,硬是要开 T 次门,若开完了 N 扇门还没
到 T 次,锴锴便又回到第一扇门,把它关上,再打开„„(好无聊)
锴锴是一位好奇心很强的小盆友,现在,他想知道在开完全部门
后,他一共试错了多少次。
输入:
第一行两个整数,N(1<=N<=10 5 )和 T(1<=T<=10 9 )
第二行到第 N+1 行,第 i+1 行一个数 ai 代表第 i 号钥匙开 ai 号门
输出:
锴锴的试错次数

输入:

3 5

1

2

3

输出:

4

输入:

4 6

4

2

1

3

输出:

13

 

输入:

10 7

1

3

2

4

5

7

6

8

9

10

输出:

25

 

思路:

其实只要暴力跑第一遍,之后的会循环,取模数就ok了

 

#include <cstdio>
#include <iostream>
using namespace std;
#define GC getchar()
#define R register
#define MAXN 100000+5
#define ll long long

template <typename T> inline void read(T &x);

int N,T,ans=0;
int k[MAXN];
int d[MAXN];
ll sec[MAXN];

int main()
{
    freopen("lock.in","r",stdin);
    freopen("lock.out","w",stdout);
    read(N),read(T);
    for(R int i=1;i<=N;i++) read(k[i]),d[k[i]]=i; // 存下门的位置
    ll now=1,ans1=0;
    for(R int i=1;i<=N;i++)
    {
        ans1+=(d[i]+N-now)%N;
        now=d[i];
        if(i==T) {printf("%lld\n",ans1);return 0;}
    }// 暴力跑一次
    now=d[N];//记下最后一次的位置
    for(R int i=1;i<=N;i++)
    {
        if(sec[i]==now) continue;
        sec[i]=sec[i-1];//继承
        sec[i]+=(d[i]+N-now)%N; //
        now=d[i];
    }
    ll ans=ans1;
    ans+=(ll)(T/N-1)*sec[N]+sec[T%N];
    printf("%lld\n",ans);
    return 0;
}

template <typename T>
inline void read(T &x)
{
    x=0;char a=GC;int f=1;
    for(;a>'9'||a<'0';a=GC) if(a=='-') f=-1;
    for(;a>='0'&&a<='9';a=GC) x=(x<<1)+(x<<3)+(a^48);
    x*=f;
}

 

转载于:https://www.cnblogs.com/000226wrp/p/11357595.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值