luogu_P2054 bzoj 1965 洗牌 题解 快速幂 快速乘
Posted ChrisK
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu_P2054 bzoj 1965 洗牌 题解 快速幂 快速乘相关的知识,希望对你有一定的参考价值。
题目链接:
Luogu:https://www.luogu.org/problem/P2054
bzoj:https://www.lydsy.com/JudgeOnline/problem.php?id=1965
找到规律:
上一次在x位置,下一次就会在 x*2%(n+1) 位置
那么就是要求:
x * (2^m) = L(mod n+1)
第一反应exgcd,但是突然感觉有点不太优秀。
因为n是偶数(题目说了)
所以2和n+1为互质
所以设 z * 2 =1(mod n+1)
z就为2在mod n+1下的逆元
z * 2 +(n+1)*y = 1
当 y=-1 时得出 z 最小为 n/2+1
所以 x=(n/2+1)^ m *L (mod n+1)
用一个快速幂和一个快速乘就可以切了。
不用快速乘中间会爆成负数。
代码如下:
#include<bits/stdc++.h> #define ll long long using namespace std; const ll maxn=1e10+10; ll n,m,l; inline ll qm(ll x,ll y){ ll mod=(n+1),ans=0; x%=mod; while(y){ if(y&1) ans=(ans+x)%mod; x=(x+x)%mod; y>>=1; } return ans%mod; } inline ll qp(ll x,ll y){ ll mod=(n+1),ans=1; x%=mod; while(y){ if(y&1) ans=qm(ans,x)%mod; x=qm(x,x)%mod; y>>=1; } return ans%mod; } int main() { scanf("%lld%lld%lld",&n,&m,&l); ll ans=qp(n/2+1,m); ans=qm(ans,l); printf("%lld\n",ans); //system("pause"); return 0; }
以上是关于luogu_P2054 bzoj 1965 洗牌 题解 快速幂 快速乘的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1965 [Ahoi2005]SHUFFLE 洗牌 数学
bzoj1965[Ahoi2005]SHUFFLE 洗牌 - 快速幂