辽宁省赛2010 G - NEW RDSP MODE I【思路题】(省赛选拔赛之个人赛9)

题目链接:https://ac.2333.moe/Problem/view.xhtml?id=1225

比赛链接:https://vjudge.net/contest/157779#overview

题目大意:给定n、m、x,原始序列是1~n;问m次操作之后的序列的前1~x个数是什么;每次操作,先取出偶数位置的数,按位置顺序构成一个序列a,再取出奇数位置的数,按位置顺序构成一个序列b,最后新的序列就是a+b。

分析:和上次的洗牌问题差不多,洗牌问题是判断第一个数1的位置的变化,问多少次操作之后能回到原来的顺序。
而这道题的操作差不多,我们需要判断m次操作后第1~X的位置分别是几。观察的时候我们可以只看第一个位置,找出其变化规律(和洗牌问题的规律类似):
      当pos(当前位置的数字)<=n/2时,下一次的变化就是pos*=2;
      否则:pos=(pos-n/2)*2-1;
就这样判断m次操作后每个位置的数是多少。
但m很大,这样肯定会超时,我们可以预处理一下m,根据洗牌问题的启发,我们先判断多少次之后会变回原来的顺序,然后让m取余这个数,再操作m次就行了。

洗牌问题:http://blog.csdn.net/jane_jxr/article/details/65627522

CODE:

#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
const double eps=0.0001;
const int maxn=10005;
int n,m,x;
int judge(int xx,int kk)//kk次操作之后xx位置的数是什么
{
    int pos=xx;
    while(kk--)
    {
        if(pos<=n/2)
            pos=pos*2;
        else
            pos=(pos-n/2)*2-1;
    }
    return pos;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&x))
    {
       // cout<1)
                printf(" ");
            printf("%d",ans);
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(思路题,比赛题解及补题)