2018.11.07 bzoj1965: [Ahoi2005]SHUFFLE 洗牌(快速幂+exgcd)

28 篇文章 0 订阅
10 篇文章 0 订阅

传送门
发现自己的程序跑得好慢啊233.
管他的反正AC了


先手玩样例找了一波规律发现题目要求的就是 a ∗ 2 m ≡ l ( m o d n + 1 ) a*2^m\equiv l \pmod {n+1} a2ml(modn+1)
然后脑补了一波 s b sb sb数学证明。
假设当前牌 a a a在第 p p p个位置(为了方便假设在左半边,右半边的差不多)。
然后在这一次洗牌之后会有 2 ∗ ( p − 1 ) + 1 = 2 ∗ p − 1 2*(p-1)+1=2*p-1 2(p1)+1=2p1张牌在它的前面。
于是它移到了第 2 ∗ p 2*p 2p个位置。
证毕。
然后为了防止爆 l o n g l o n g long long longlong我手写了一个快速乘估计就是这个地方慢了(都是借口明明是自己菜。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,l,a,b;
inline ll ksc(ll x,ll p,ll mod){ll ret=0;for(;p;p>>=1,x=(x+x)%mod)if(p&1)ret=(ret+x)%mod;return ret;}
inline ll ksm(ll x,ll p,ll mod){ll ret=1;for(;p;p>>=1,x=ksc(x,x,mod))if(p&1)ret=ksc(ret,x,mod);return ret;}
inline ll gcd(ll a,ll b){while(b){ll t=a;a=b,b=t%a;}return a;}
inline void exgcd(ll a,ll b,ll&x,ll&y){
	if(!b){x=1,y=0;return;}
	exgcd(b,a%b,x,y);
	ll tmp=x;
	x=y,y=tmp-a/b*y;
}
int main(){
	cin>>n>>m>>l,a=ksm(2ll,m,n+1),b=n+1;
	ll g=gcd(a,b),x,y;
	a/=g,b/=g,l/=g;
	exgcd(a,b,x,y);
	x=(ksc(x,l,b)+b)%b;
	cout<<x;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值