【BZOJ1965/Ahoi2005】SHUFFLE 洗牌
阿新 • • 發佈:2018-12-20
解析:
法一:找規律 手玩樣例可以發現原位置為的數經過次洗牌後位置變為: 法二:稍微嚴謹的數學證明 如果當前位置為變化一次後到哪個位置,存在兩種情況: 1. 易知變到第個位置。 2. 易知變到第個位置。 前面顯然有。 後面有。 所以我們可以認為每次操作之後都由位置變成了位置。 所以原問題變為求解,轉換一下得到: 注意到與是互質的。所以直接用擴歐求逆元再用快速冪求解即可。
程式碼:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,l,mod,x,y;
inline int mul(int a,int b){int ans=0;while(b){if(b&1)ans=(ans+a)%mod;b>>= 1,a=(a+a)%mod;}return ans;}
inline int ksm(int a,int b){int ans=1;while(b){if(b&1)ans=mul(ans,a);b>>=1,a=mul(a,a);}return ans;}
inline void exgcd(int a,int b)
{
if(!b) x=1,y=0;
else
{
exgcd(b,a%b);
int t=x;
x=y,y=t-a/b*x;
}
}
signed main()
{
cin>>n>>m>>l,mod=n+1;
exgcd(ksm(2,m),mod);
x=(x%mod+mod)%mod; //若不轉成最小正整數解可能是負數快速乘會T!
cout<<mul(l,x)<<"\n";
return 0;
}