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

来源:互联网 发布:辽阳有线淘宝营业厅 编辑:程序博客网 时间:2024/04/23 14:55

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