一眼看到这题,可以写出一个非常naive的dp:
设 (dp[i][j]) 表示第 (i) 次操作后钥匙在第 (j) (从左到右为 (0,1,2))个位置的概率,那么 (dp[i][1]) 就是答案。
[
dp[i][0]=dp[i-1][1]/2+dp[i-1][0]/2
]
[dp[i][1]=dp[i-1][0]/2+dp[i-1][2]/2
]
[dp[i][2]=dp[i-1][1]/2+dp[i-1][2]/2
]
解释:
第一行:留在第0个位置可以有 (frac12) 的概率从中间挪过来,也有 (frac12) 的概率上次移动没有移动它
第二行:留在第1个位置有 (frac12) 的概率从左边移过来,也有 (frac12) 的概率从右边移过来
第三行:同第一行
显然 (dp[i][0]) 与 (dp[i][2]) 是等价的,合并为 (dp[i][0]) ,带入 (dp) 式子得
[dp[i][0]=dp[i-1][1]/2+dp[i-1][0]/2
]
[dp[i][1]=dp[i-1][0]
]
第二行再带入第一行:
[dp[i][0]=dp[i-1][0]/2+dp[i-2][0]/2
]
显然可以把 (0) 改成 (1)
[dp[i][1]=dp[i-1][1]/2+dp[i-2][1]/2
]
如果还不够明显,那就再写的简洁一些,设 (ans=a_n):
[a_n=dfrac{a_{n-1}+a_{n-2}}2
]
边界:(a_0=1,a_1=0)
这就是一个典型的二阶递推啊!
可以用特征方程来解决,不会自行百度(就是解几个方程求通项公式而已)
(一小点计算过后,我们得到了)
(large ans=dfrac{2^{n-1}- (-1)^{n-1}}{3*2^{n-1}})
(n) 就是操作的次数
再看看题,发现有一个问题还没有很好的解决:先约分再取模
发现分母只有 (2,3) 这两个因数。 (2) 肯定没法约掉,因为分子显然是奇数
那 (3) 呢?
由于 ((-1)^{n-1}) 的值与 (n) 有关,分类讨论一下((2^2\%3=1 ightarrow2^{2n}\%3=1)):
- (n) 为奇数:(2^{n-1}\%3=1,(-1)^{n-1}\%3=1,ans\%3=0)
- (n) 为偶数:(2^{n-1}\%3=2,(-1)^{n-1}\%3=-1,ans\%3=0)
所以 (3) 肯定是约得掉的!
注意指数取模应该根据费马小定理模 (mod-1)
#define int long long
const int N=100010;
const int mod=1e9+7;
int n,a[N],sum=1;
int qpow(int n,int k) {
k=(k%(mod-1)+mod-1)%(mod-1);
int res=1;
while(k) {
if(k&1)res=1ll*res*n%mod;
n=1ll*n*n%mod,k>>=1;
}
return res;
}
const int inv3=qpow(3,mod-2);
int ans1,ans2;
signed main() {
n=rd();
for(int i=1;i<=n;++i)a[i]=rd(),sum=sum*(a[i]%(mod-1))%(mod-1);
ans1=(qpow(2,sum-1)+((sum&1)?-1:1))%mod*inv3%mod;
ans2=qpow(2,sum-1);
printf("%lld/%lld
",ans1,ans2);
return 0;
}