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; }