欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-02 21:30:45
...

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


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

#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;
}
相关标签: 数学