题目:BZOJ1965
解析:
法一:找规律
手玩样例可以发现原位置为
p
p
p的数经过
m
m
m次洗牌后位置变为:
p
∗
2
m
m
o
d
(
n
−
1
)
p*2^mmod(n-1)
p∗2mmod(n−1)
法二:稍微严谨的数学证明
如果当前位置为
p
p
p变化一次后到哪个位置,存在两种情况:
1.
p
≤
n
2
p\le\frac{n}{2}
p≤2n
易知变到第
2
p
2p
2p个位置。
2.
n
2
<
p
≤
n
\frac{n}{2}<p\le n
2n<p≤n
易知变到第
(
p
−
n
/
2
)
∗
2
−
1
=
2
p
−
n
−
1
(
p
−
n
/
2
)
∗
2
−
1
=
2
p
−
(
n
+
1
)
(p−n/2)∗2−1=2p−n−1(p−n/2)∗2−1=2p−(n+1)
(p−n/2)∗2−1=2p−n−1(p−n/2)∗2−1=2p−(n+1)个位置。
前面显然有
2
p
≤
n
2p\le n
2p≤n。
后面有
p
≥
n
/
2
+
1
=
>
2
p
≥
n
+
2
=
>
2
p
>
n
+
1
p\ge n/2+1=>2p\ge n+2=>2p > n+1
p≥n/2+1=>2p≥n+2=>2p>n+1。
所以我们可以认为每次操作之后都由
p
p
p位置变成了
2
l
m
o
d
(
n
+
1
)
2lmod(n+1)
2lmod(n+1)位置。
所以原问题变为求解
x
∗
2
m
≡
L
(
m
o
d
(
n
−
1
)
)
x*2^m\equiv L(mod(n-1))
x∗2m≡L(mod(n−1)),转换一下得到:
x
≡
L
/
2
m
(
m
o
d
(
n
−
1
)
)
x\equiv L/2^m(mod(n-1))
x≡L/2m(mod(n−1))
注意到
2
m
2^m
2m与
n
+
1
n+1
n+1是互质的。所以直接用扩欧求逆元再用快速幂求解即可。
代码:
#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;
}