Loading

题解 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;
}
posted @ 2020-08-12 08:13  zzctommy  阅读(153)  评论(0编辑  收藏  举报