NBUT 1225 NEW RDSP MODE I(找规律)(快速幂)

115 篇文章 0 订阅
15 篇文章 0 订阅

NEW RDSP MODE I

问题描述

Little A has became fascinated with the game Dota recently, but he is not a good player. In all the modes, the rdsp Mode is popular on online, in this mode, little A always loses games if he gets strange heroes, because, the heroes are distributed randomly.

Little A wants to win the game, so he cracks the code of the rdsp mode with his talent on programming. The following description is about the rdsp mode:

There are N heroes in the game, and they all have a unique number between 1 and N. At the beginning of game, all heroes will be sorted by the number in ascending order. So, all heroes form a sequence One.

These heroes will be operated by the following stages M times:

1.Get out the heroes in odd position of sequence One to form a new sequence Two;

2.Let the remaining heroes in even position to form a new sequence Three;

3.Add the sequence Two to the back of sequence Three to form a new sequence One.

After M times’ operation, the X heroes in the front of new sequence One will be chosen to be Little A’s heroes. The problem for you is to tell little A the numbers of his heroes.

输入
There are several test cases.
Each case contains three integers N (1<=N<1,000,000), M (1<=M<100,000,000), X(1<=X<=20).
Proceed to the end of file.
输出
For each test case, output X integers indicate the number of heroes. There is a space between two numbers. The output of one test case occupied exactly one line.
样例输入
5 1 2
5 2 2
样例输出
2 4
4 3
提示
In case two: N=5,M=2,X=2,the initial sequence One is 1,2,3,4,5.After the first operation, the sequence One
is 2,4,1,3,5. After the second operation, the sequence One is 4,3,2,1,5.So,output 4 3.
来源
辽宁省赛2010

题意:1~N个数字组成数组A,将数组中奇数位组成一个数组B,偶数位组成一个数组C,然后将B连接到C后面,求执行M次,输出最后的前X位数。

思路:通过多列举一下样例我们可以发现它是有循环节的,而且它的循环节≤n,所以我们可以先找到循环节T,利用T去约m,然后再将很小的m拿去模拟,输出前x个

所以,我们只需要模拟1的位置,一直模拟到1出现在第一个位置时,循环节T就算出来了(复杂度O(n))。找到循环节T之后,我们令m=m%T.这样m就变成<=n的了,然后我们对前x个数字,分别模拟m次,因为现在的m<=n,所以复杂度O(xn)

代码:

#include<stdio.h>
typedef long long LL;

LL Find(LL n,LL m)//寻找循环节
{
    LL tot=1,ans=0;
    while(true)
    {
        ans++;
        if(tot&1)
            tot=n/2+(tot+1)/2;
        else
            tot/=2;
        if(tot==1)
            return ans;
    }
}

LL solve(LL k,LL n,LL m)//每一位模拟m次操作
{
    for(LL i=1;i<=m;++i)
        k=k*2%n;
    return k;
}

int main()
{
    LL n,m,x;
    while(~scanf("%I64d%I64d%I64d",&n,&m,&x))
    {
        LL cnt=Find(n,m);
        m%=cnt;
        if(!(n&1))//当n为偶数的时候要+1,因为n为偶数的时候,取模后下标可能为0,
            ++n;//当n为奇数时,第n位数在变换中位置是不变的,所以情况和n-1一样
        for(LL i=1;i<=x;++i)
            printf(i==x?"%I64d\n":"%I64d ",solve(i,n,m));
    }
    return 0;
}



但是通过上面的模拟m次过程我们可以发现,模拟过程实际上就是不断地×2%n的过程,这样好像和快速幂的过程类似,所以我们把模拟过程可以用快速幂写一下

代码:

#include<stdio.h>
typedef long long LL;
LL n,m,x;

LL quick_mod()
{
    LL res=1,k=m,x=2;
    while(k)
    {
        if(k&1)
            res=res*x%n;
        x=x*x%n;
        k>>=1;
    }
    return res;
}


int main()
{
    while(~scanf("%I64d%I64d%I64d",&n,&m,&x))
    {
        if(!(n&1))
            ++n;
        LL tmp=quick_mod();
        printf(x==1?"%I64d\n":"%I64d ",tmp);
        LL ans=tmp;
        for(int i=2;i<=x;++i)
            printf(i==x?"%I64d\n":"%I64d ",ans=(ans+tmp)%n);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值