算法与数据结构实验题 2.3 泡泡的饭碗

算法与数据结构实验题 2.3 泡泡的饭碗
★实验任务
饱了吗终于发现泡泡破解了它的代码并借此白吃白喝。饱了吗当即改变了自己的幸运儿生成源码,但是,又被机智的泡泡偷瞄到了,机智的泡泡马上意识到可能要饭碗不保了:
每当有人参与抽奖,这个人就进入队列。当人数达到 n 的时候开奖一次。
1. 开奖时,将执行 m 次操作,每次操作挑一个不超过 200 的数 d,且保证 d不超过人数的一半,然后把第 D 个人和第 n-D+1 个人这两个人之间的队伍反转:
2. 反转前:1,2,…,D-1,D,D+1,…, n-D+1, n-D+2,…n(从左往右编号)
3. 反转后:1,2,…,D-1,n-D+1,n-D,…, D+1, D, n-D+2…n(这里的编号是旋转前从左到右的编号)
m 次操作完后从队头开始报号,没报到 x 的回到队尾,报到 x 的就是幸运儿啦;
机智的泡泡马上又意识到,当 n 和 m 次操作和 x 的值已知的时候,幸运儿仍然是可以预知到是第几个参与抽奖的人的。
机智的泡泡马上又意识到,自己的饭碗保住了。
但是!机智的泡泡马上意识到一个问题,这个预知结果的代码不好打。
但是!机智的泡泡马上想起了你。
机智的泡泡马上把锅又扔给了你。
★数据输入
输入第一行为三个正整数 n,m,x。
接下来 m 行,第 i 行给出第 i 次操作的 d,如题;
对于 80%的数据,2<=n<=2000,1<=m<=2000;
对于 100%的数据,2<=n<=100000,1<=m<=100000
1<=x<=1000,000,000,1<=d<=min(n/2,200);
★数据输出
输出幸运儿是第几个参加抽奖的人。
输入示例
5 2 1
2
1
输出示例
5

输入示例
5 4 3
2
1
2
1
输出示例
3


思路:
因为数据量比较大,所以如果用算法跑完整个过程,一定会超时。
根据题意,这个队列是对称反转,那么我们只需要知道所求数字有没有反转就行。因为有n个人在玩游戏,所以结果肯定是1到n,那么我们可以通过取模,直接确定是哪一个位置上的人是最终答案,再确定这个位置翻转了几次就OK。
这里的取模比较特殊,正常x%n会得到0~n-1的数字,所以我们要用(x-1)%n+1就可以得到1~n的数字
附上大佬代码:

#include<stdio.h>       
int main()    
{    
    int n,m,x,tmp;    
    int cnt=0;      //会影响取模后的x的翻转次数    
    int ans;    

    scanf("%d%d%d",&n,&m,&x);    

    x = (x-1)%n+1;          //取模,注意不能为0,所以是(x-1)%n+1    
    ans = x;                 
    x = x<(n-x+1)?x:(n-x+1);    //由于d<(n/2) 如果取模后的x在区间右边,把它变到左边来    
    //printf("%d\n",x);    

    for(int i=0;i<m;i++)    
    {    
        scanf("%d",&tmp);    
        if(tmp <= x) cnt++; //会影响到取模后的x    
    }    

    //printf("%d\n",cnt);    
    if(cnt&1){              //奇数次才会影响ans    
        ans = n-ans+1;    
    }    

    printf("%d\n",ans);    

    return 0;    
}

时间复杂度为O(1)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值