bzoj1965: [Ahoi2005]SHUFFLE 洗牌

题意

自己看

题解

我们设一开始的数为X
我们可以发现变化规则为:
X=2*X X<= (n/2)
X=2*X-(n+1) X>n/2
于是这个其实可以总结为X=2*X % (n+1)
于是就可以做了
就相当于X* 2m -(n+1)*Y=l
这样就可以用扩展欧几里得做了

#include<cstdio>
typedef long long LL;
LL n,m,l;
LL get (LL x,LL y)
{
    if (y==0) return 1;
    if (y==1) return x;
    LL lalal=get(x,y/2);lalal=lalal*lalal%n;
    if (y%2!=0) lalal=lalal*x%n;
    return lalal;
}
LL exgcd (LL a,LL b,LL &x,LL &y)
{
    if (a==0)
    {
        x=0;y=1;
        return b;
    }
    LL tx,ty;
    LL d=exgcd(b%a,a,tx,ty);
    x=ty-(b/a)*tx;y=tx;
    return d;
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&l);n++;
    LL lalal=get(2,m);
    //X*lalal-n*Y=L
    LL x,y;
    LL d=exgcd(lalal,n,x,y);
    printf("%lld",(x*(l/d)%(n/d)+(n/d))%(n/d));
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值