bzoj 1965 //1965:[Ahoi2005] SHUFFLE 洗牌
更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录
方法一:乘法逆元+快速幂+快速乘
33ms / 776.00KB / 476B C++
//1965:[Ahoi2005] SHUFFLE 洗牌
//在线测评地址https://www.luogu.org/problem/P2054
//此文https://www.cnblogs.com/chenxiaoran666/p/BZOJ1965.html思路写得不错,摘抄如下:
作个解释:2019-10-22 20:37
移动第1次后的位置为2x%(n+1)
移动第2次后的位置为2*(2x%(n+1))%(n+1)=x*2^2%(n+1)
移动第3次后的位置为2*(x*2^2%(n+1))%(n+1)=x*2^3%(n+1)
......
移动第m次后的位置为x*2^m%(n+1)
//此文https://blog.csdn.net/Fsss_7/article/details/50648297思路不错,摘抄如下:
/*
一个置换的题。。我们对样例进行简单的分析可知经过一次变换有(1->2,2->4,3->6,4->1,5->3,6->5),然后我们就能发现p[a]=a*2%(n+1)。。然后我们设答案为X即X=p[l],所以有X*(2^m)=l%(n+1)并且2模n+1的逆元为n/2+1,所以我们将等式变换一下就有X=l*(n/2+1)^m%(n+1),然后就只要用快速幂处理这个式子就行了,同时要注意数据是10^10可能乘爆,用快速乘即可。
解释一下:n+1为奇数,2*(n/2+1)=1%(n+1)故2^m*(n/2+1)^m=1%(n+1),(n/2+1)^m为2^m关于模(n+1)的乘法逆元。
*/
//因0<N≤10^10 ,0 ≤M≤10^10,乘法long long要溢出,故采用快速乘。
//样例通过,提交AC.2019-10-22 21:33
#include <stdio.h>
#define LL long long
LL n,m,L;
LL quick_mul(LL a,LL b){//5*7 b=7 ans=5 a=10;b=3 ans=15 a=20;b=1 ans=35 a=40;b=0
LL ans=0;
while(b){
if(b&1)ans=(ans+a)%(n+1);
a=(a+a)%(n+1);
b>>=1;
}
return ans;
}
LL quick_pow(LL a,LL b){
LL ans=1;
while(b){
if(b&1)ans=quick_mul(ans,a);
a=quick_mul(a,a);
b>>=1;
}
return ans;
}
int main(){
scanf("%lld%lld%lld",&n,&m,&L);
printf("%lld\n",quick_mul(L,quick_pow(n/2+1,m)));
return 0;
}
方法二:扩展欧几里得算法+快速幂+快速乘
方法三:打表找规律