BZOJ1965: [Ahoi2005]SHUFFLE 洗牌

来源:互联网 发布:华科软件学院 编辑:程序博客网 时间:2024/05/21 09:01

Portal

由样例可以得到1>2,2>4,3>6,4>1,5>3,6>5.
可以得出一次洗牌后pos[i]=(2i)mod(n+1)
那么经过m次洗牌后,初始位置为x移动到了位置(2mx)modn+1
最后也就是求不定方程2mxLmod(n+1)最小正整数解。

快速幂+快速乘(LX会爆longlong

【代码】

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <map>#define N 10000005#define INF 0x7fffffffusing namespace std;typedef long long ll;typedef pair<int,int> pa;ll read(){    ll x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}ll n,m,L,X,Y;ll Qpow(ll x,ll y){    ll rtn=1;    while(y)    {        if(y&1) rtn=rtn*x%n;        x=x*x%n;y>>=1;    }    return rtn;}ll Qmul(ll x,ll y){    ll rtn=0;    while(y)    {        if(y&1) rtn=(rtn+x)%n;        x=(x<<1)%n;y>>=1;    }    return rtn;}ll exgcd(ll a,ll b,ll &x,ll &y){    ll rtn=a;    if(b) {        rtn=exgcd(b,a%b,y,x);        y-=(a/b)*x;    }    else x=1,y=0;    return rtn;}int main(){    n=read()+1,m=read(),L=read();    ll Gcd=exgcd(Qpow(2,m),n,X,Y);    X=Qmul(X,L);    while(X<=0) X+=n/Gcd;    printf("%lld\n",X);    return 0;}
0 0
原创粉丝点击