持续创作,加速成长!这是我参与「掘金日新计划 · 1 月更文挑战」的第23天,点击查看活动详情
题目链接
题目
As we all know Barney's job is "PLEASE" and he has not much to do at work. That's why he started playing "cups and key". In this game there are three identical cups arranged in a line from left to right. Initially key to Barney's heart is under the middle cup.
Then at one turn Barney swaps the cup in the middle with any of other two cups randomly (he choses each with equal probability), so the chosen cup becomes the middle one. Game lasts turns and Barney independently choses a cup to swap with the middle one within each turn, and the key always remains in the cup it was at the start.
After n-th turn Barney asks a girl to guess which cup contains the key. The girl points to the middle one but Barney was distracted while making turns and doesn't know if the key is under the middle cup. That's why he asked you to tell him the probability that girl guessed right.
Number n of game turns can be extremely large, that's why Barney did not give it to you. Instead he gave you an array such that
in other words, n is multiplication of all elements of the given array.
Because of precision difficulties, Barney asked you to tell him the answer as an irreducible fraction. In other words you need to find it as a fraction such that , where is the greatest common divisor. Since and can be extremely large, you only need to find the remainders of dividing each of them by .
Please note that we want of and to be 1, not of their remainders after dividing by .
题目大意
有三个杯子放成一行,一开始中间的杯子里有一个球,每次可以选择左右两边的杯子和中间的杯子交换位置,问 次操作后球在中间的杯子里的概率,将其化为最简分数后分子分母分别对 取模后输出。
思路
我们每次操作可以从左右两个杯子中选择一个和中间的杯子交换,操作 次就会有 种移动方案,我们只需要求其中的哪些些移动方案会使得球最终处于中间的杯子即可。
记三个杯子分别用 表示。 容易发现,经过一轮交换后:
- 如果球在 里,说明:交换前球在 里,本轮交换了 和 ;或者交换前球在 里,本轮交换了 和 。
- 如果球在 里,说明:交换前球在 里,本轮交换了 和 ;或者交换前球在 里,本轮交换了 和 。
- 如果球在 里,说明:交换前球在 里,本轮交换了 和 ;或者交换前球在 里,本轮交换了 和 。
易知左右两个杯子任意轮后有球的概率相同,将二者的方案合并,设 表示前 轮交换后球在左(右)边的杯子里, 表示前 轮交换后球在中间的杯子里,转移方程如下:
而我们的 非常大,我们可以进行矩阵优化快速幂求解上面的东西。显然系数矩阵如下:
进而:
因为 ,所以对于 ,我们只需要把每次转移了 次的矩阵作为系数矩阵进行后续的转移即可。
此时我们算出来的结果是没有通分就取余的结果,已知分母是 2 的整次幂,我们只需要考虑分子中有多少个因数 2 即可。观察动态规划的转移方程,我们可以发现 一直是奇数, 一直是奇数的二倍,则我们把求出来的没有通分就取余的分子分母同时乘以 2 对模数的逆元即可。
代码
#include <bits/stdc++.h>
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
struct martix{
LL a[2][2];
martix operator * (const martix b) const
{
martix c;
c.a[0][0]=(a[0][0]*b.a[0][0]+a[0][1]*b.a[1][0])%mod;
c.a[0][1]=(a[0][0]*b.a[0][1]+a[0][1]*b.a[1][1])%mod;
c.a[1][0]=(a[1][0]*b.a[0][0]+a[1][1]*b.a[1][0])%mod;
c.a[1][1]=(a[1][0]*b.a[0][1]+a[1][1]*b.a[1][1])%mod;
return c;
}
};
LL poww(LL a,LL b)
{
LL ans=1;
for (;b;b>>=1,a=a*a%mod)
if (b&1) ans=ans*a%mod;
return ans;
}
martix ans;
martix poww(martix a,LL b)
{
ans.a[0][0]=ans.a[1][1]=1;
ans.a[0][1]=ans.a[1][0]=0;
for (;b;b>>=1,a=a*a)
if (b&1) ans=ans*a;
return ans;
}
int solve()
{
int n;
scanf("%d",&n);
martix a;
a.a[0][0]=a.a[0][1]=1;
a.a[1][0]=2;
a.a[1][1]=0;
LL x,y=2;
for (int i=1;i<=n;++i)
{
scanf("%lld",&x);
a=poww(a,x);
y=poww(y,x);
}
x=poww(2,mod-2);
y=y*x%mod;
x=a.a[1][1]*x%mod;
printf("%lld/%lld\n",x,y);
}
int main()
{
int T=1;
solve();
return 0;
}