zoukankan      html  css  js  c++  java
  • 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

    四十分:直接模拟,O(NK)

    六十分:可以发现除了最开始的第一次以外一直都是在以N循环的,可以预处理出打开第N扇门的尝试,再来模拟;

    一百分:既然每次循环尝试次数都是一样的,那我们只用求每N扇门的尝试和前K%N扇门的尝试,复杂度O(N)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        char ch;
        while((ch=getchar())<'0'||ch>'9'){;}
        int res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
        return res;
    }
    int n,k,v[100005],place[100005],first,ans[100005];
    long long tot[100005],qfe;
    int main(){
        //freopen("unlock.in","r",stdin);
        //freopen("unlock.out","w",stdout);
        n=read(),k=read();
        for(int i=1;i<=n;i++)
        {
            v[i]=read();
            place[v[i]]=i;
        }
        first=place[1]-1;
        ans[1]=place[1]-place[n];
        if(ans[1]<0) ans[1]+=n;
        for(int i=2;i<=n;i++)
        {
            ans[i]=place[i]-place[i-1];
            if(ans[i]<0)
            ans[i]=ans[i]+n;
        }
        for(int i=1;i<=n;i++)
        {
            tot[i]=tot[i-1]+ans[i];
        }
        int y=k/n;
        qfe=y*tot[n]+tot[k-y*n]-tot[1]+first;
        cout<<qfe<<endl;
        return 0;
    }
  • 相关阅读:
    3.2.1 正則表達式的语法(1)
    朴素贝叶斯(naive bayes)
    有方向的运动js
    碰撞检測之OBB-OBB的SweepTest
    左右上下都能滚动的效果
    C语言中 fputs() fgets() 的使用方法
    Apache Module mod_ssl
    "ssllabs" website and "testssl" website
    Google发布SSLv3漏洞简要分析报告
    为什么要使用TLSv1.2和System SSL?
  • 原文地址:https://www.cnblogs.com/forever-/p/9736089.html
Copyright © 2011-2022 走看看