CodeForces 696C PLEASE
快速幂,费马小定理,逆元。
设$dp[n]$表示$n$次操作之后的概率,那么$dp[n] = \frac{{(1 - dp[n - 1])}}{2}$。$1-dp[n - 1]$表示上一次没有在中间的概率,除以$2$表示$n$次操作之后的情况数是$n-1$次操作之后的两倍,所以要除以$2$,这个画画图就可以知道了。
也就是说,现在我们知道了$ - 2×dp[n] = dp[n - 1] - 1$
我们假设$ - 2*(dp[n] + X) = dp[n - 1] + X$,利用待定系数法,可以求得$X = - \frac{1}{3}$。
那么,$\frac{{dp[n] - \frac{1}{3}}}{{dp[n - 1] - \frac{1}{3}}} = - \frac{1}{2}$。 因此,$dp[n] - \frac{1}{3}$是首项为$ - \frac{1}{3}$,公比为$ - \frac{1}{2}$的等比数列。
可以计算得到:$dp[n] = \frac{{{{( - 1)}^n} + {2^{n - 1}}}}{{3×{2^{n - 1}}}}$。
通过观察可以发现,${{{( - 1)}^n} + {2^{n - 1}}}$与${{2^{n - 1}}}$之间必然是互质的,那么分子与分母之间的公约数要么是$3$,要么没有公约数。
所以,如果分子能被$3$整除,那么分子分母同除以$3$,即分子和分母再$×3$的逆元。
求解${{2^{n - 1}}}$可以通过费马小定理:${a^x}\% p = {a^{x\% \phi (p) + \phi (p)}}\% p$。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0;while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } const int maxn=100010; int k; LL mod=1e9+7,pmod=1e9+6; LL n,a[maxn]; LL extend_gcd(LL a,LL b,LL &x,LL &y) { if(a==0&&b==0) return -1; if(b==0){x=1;y=0;return a;} LL d=extend_gcd(b,a%b,y,x); y-=a/b*x; return d; } LL mod_reverse(LL a,LL n) { LL x,y; LL d=extend_gcd(a,n,x,y); if(d==1) return (x%n+n)%n; else return -1; } LL POW(LL a,LL b,LL m) { LL d,t; d=1; t=a; while (b>0) { if (b%2==1) d=(d*t)%m; b/=2; t=(t*t)%m; } return d; } int main() { scanf("%d",&k); for(int i=1;i<=k;i++) scanf("%lld",&a[i]); LL f=1,z=1; for(int i=1;i<=k;i++) { f=f*(a[i]%2)%2, z=z*(a[i]%pmod)%pmod; } z=(z-1+pmod)%pmod+pmod; if(f%2==0) f=1; else f=-1; LL fz=POW(2,z,mod); fz=(fz+f+mod)%mod; LL fm=POW(2,z,mod); z=1; for(int i=1;i<=k;i++) z=z*(a[i]%2)%2; z=(z-1+2)%2+2; LL t=POW(2,z,3); t=(t+f+3)%3; if(t==0) fz=fz*mod_reverse(3,mod)%mod; else fm=3*fm%mod; printf("%lld/%lld\n",fz,fm); return 0; }