我感觉这辈子是想不到了,看了大佬的题解,才知道自己有多菜。
翻译:
小A最近对Dota的比赛着迷,但他不是一个好球员。在所有模式中,rdsp模式在网上流行,在这种模式下,如果他得到奇怪的英雄,小A总是会丢失游戏,因为,英雄是随机分布的。
小A想要赢得比赛,所以他用他的编程才能破解了rdsp模式的代码。以下描述是关于rdsp模式的:
游戏中有N个英雄,它们都有1到N之间的唯一数字。在游戏开始时,所有英雄将按数字按升序排序。所以,所有英雄形成一个序列。
这些英雄将在以下阶段进行M次操作:
1.取出序列中奇数位置的英雄,形成一个新的序列二;
2.让剩余的英雄处于平衡状态,形成一个新的序列三;
3.将序列2添加到序列3的后面以形成新序列One。
经过M次操作后,新序列One前面的X英雄将被选为小A的英雄。你的问题是告诉小A他的英雄数量。
模拟一下该过程,奇数时 最后一位是不变的。根据大佬推的公式,
2*k 跟 2*k+1 数字的前2*k个字符变化完全相同,当为2*k+1数列,第2*k+1个数永远为2*k+1
第一个数字是 1*2^(m)%n ,第2个数字是2*2^(m)%n,第3个是3*2^(m)%n,以此类推。
计算2^n时。可采用乘法加速幂来进行快速运算。
#include<stdio.h>
#include<queue>
#include<math.h>
#include<time.h>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<stack>
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(a) a&(-a)
#define PI acos(-1)
#define shortime(a) std::ios::sync_with_stdio(a);
using namespace std;
//const LL mod=1e9+7;
//long long cmp(node a,node b){ if(a.x==b.x) return a.r>b.r;return a.x>b.x;}
LL quick(LL x,LL n,LL mod){ LL ans=1,temp=x; while(n){if(n%2==1){ ans=(ans*temp)%mod;} n/=2;temp=temp*temp%mod;}return ans%mod;}
int maxn (int a,int b,int c){return max(max(a,b),max(b,c));}
LL min(LL a,LL b) {return a<b?a:b;}
int gcd (int a,int b){return b==0?a:gcd(b,a%b);}
int main()
{
LL n,m,x;
while(~scanf("%lld%lld%lld",&n,&m,&x))
{
if(n%2==0) n++;
if(((quick(2,m,n))%n)==0) printf("%lld",n);
else
printf("%lld",(quick(2,m,n))%n);
for(int i=2;i<=x;i++)
{
if(((i*quick(2,m,n))%n)==0) printf(" %lld",n);
else
printf(" %lld",(i*quick(2,m,n))%n);
}
printf("\n");
}
return 0;
}