辽宁省赛2010 I 题
题目来源:http://www.sizaif.com:6680/problem.php?cid=1018&pid=8
题目大意:给定三个数字 n,m,x,n代表从一到n的数字组成的数组,然后每次把下标为偶数的提到前面剩下的奇数项按顺序排在后面构成一个新序列,m代表进行了m次,x代表输出前x个。
分析:自己一直在找规律结果找了一个多小时都错了,找了大神的代码看了之后发现自己是真的菜…… 大佬的思维:
a. 2*k 跟 2*k+1 数字的前2*k个字符变化完全相同,当为2*k+1数列,第2*k+1个数永远为2*k+1
b. 第一个数字是 1*2^(m)%n ,第2个数字是2*2^(m)%n,第3个是3*2^(m)%n,以此类推。
c. 计算2^n时。可采用乘法加速幂来进行快速运算。
但是大佬的的代码好像有跑零的一个BUG,之所以说是BUG因为它可以过啊!!!
然后自己改良后的代码:
#include <cstdio>
typedef long long ll;
ll qpow(ll a,ll n,ll mod)
{
ll sum=1;
while(n)
{
if(n%2==1)
sum=(a*sum)%mod;
a=(a*a)%mod;
n/=2;
}
return sum;
}
int main()
{
ll n,m,x;
while(~scanf("%lld %lld %lld",&n,&m,&x))
{
ll tt=n;
ll ss=0,ans=0;
if(n%2==0)
n++;
ss=qpow(2,m,n);
printf("%lld",ss);
ans=ss;
for(int i=1;i<x;i++)
{
ans+=ss;
ans%=n;
if(i==x-1&&tt%2==1&&x==n)
ans=n;
printf(" %lld",ans);
}
printf("\n");
}
return 0;
}
大佬的博客地址:https://blog.csdn.net/crescent__moon/article/details/19176093