P2054 [AHOI2005]洗牌

P2054 [AHOI2005]洗牌
https://www.luogu.org/problem/P2054
手推一下小数据,会发现,当前编号是x的拍,再进行m次洗牌之后的位置为(2^m)*x%(n+1);
所以我们要解这个方程组--> (2^m)*x%(n+1)==l
x=l*((2^m)^-1)%(n+1);
套扩欧求逆元就完事了,但是wa了两个点,改成__int128就过了

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(__int128 i=a;i<=b;++i)
//by war
//2019.8.7
using namespace std;
__int128 n,m,l,x,y;
void in(__int128 &x){
    __int128 y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(__int128 x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}
__int128 ksm(__int128 a,__int128 b){
    __int128 r=1;
    while(b>0){
        if(b&1)
            r=r*a%(n+1);
        a=a*a%(n+1);
        b>>=1;
    }
    return r;
}

void exgcd(__int128 a,__int128 b,__int128 &x,__int128 &y){
    if(!b){
        x=1;y=0;
        return;
    }
    exgcd(b,a%b,y,x);
    y-=a/b*x;
}

signed main(){
    in(n);in(m);in(l);
    l%=n+1;
    exgcd(ksm(2,m),n+1,x,y);
    x=(x%(n+1)+n+1)%(n+1);
    o(x*l%(n+1));
    return 0;
}

 

__int128有的OJ不支持,这是这个题的慢速乘版本

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
//by war
//2019.8.7
using namespace std;
long long n,m,l,x,y;
void in(long long &x){
    long long y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(long long x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}

long long msc(long long a,long long b){
    long long r=0;
    while(b>0){
        if(b&1)
            r=(r+a)%(n+1);
        a=(a<<1)%(n+1);
        b>>=1;
    }
    return r;
}

long long mscc(long long a,long long b){
    long long r=0,y=1;
    if((a^b)<0)  y*=-1;
    a=abs(a);b=abs(b);
    while(b>0){
        if(b&1)
            r+=a;
        a<<=1;
        b>>=1;
    }
    return r*y;
}

long long ksm(long long a,long long b){
    long long r=1;
    while(b>0){
        if(b&1)
            r=msc(r,a);
        a=msc(a,a);
        b>>=1;
    }
    return r;
}

void exgcd(long long a,long long b,long long &x,long long &y){
    if(!b){
        x=1;y=0;
        return;
    }
    exgcd(b,a%b,y,x);
    y-=mscc(a/b,x);
}

signed main(){
    in(n);in(m);in(l);
    l%=n+1;
    exgcd(ksm(2,m),n+1,x,y);
    x=(x%(n+1)+n+1)%(n+1);
    o(msc(x,l));
    return 0;
}

 

posted @ 2019-08-07 19:34  WeiAR  阅读(181)  评论(0编辑  收藏  举报