题解 CF696C 【PLEASE】
一眼看到这题,可以写出一个非常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\rightarrow2^{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\n",ans1,ans2);
return 0;
}
路漫漫其修远兮,吾将上下而求索