codeforces_697E PLEASE

题目:

   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 n 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 a1, a2, ..., ak 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 p / q such that , where is the greatest common divisor. Since p and q can be extremely large, you only need to find the remainders of dividing each of them by .
   Please note that we want of p and q to be 1, not of their remainders after dividing by .

思路:

   设为第操作时,硬币在的情况数,那么:
  
  
  
   那么,因为在中的情况和在中的情况完全一致,所以,根据等比数列性质,也就等于
   根据这个式子,只要算出总情况数,就能算出。但是题目要求输出取模前约分的结果,而在计算中不可能不约分(除非开高精),发现。约分要且只要约掉一个即可。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inv3=333333336;
const int inv2=500000004;
int pow(int x,ll k){
    int ans=1;
    while(k){
        if(k&1)ans=(ll)ans*x%mod;
        x=(ll)x*x%mod;
        k>>=1;
    }
    return ans;
}
#define MN 100005
ll a[MN];
int main(){
    int k;
    scanf("%d",&k);
    bool odd=1;
    for(int i=1;i<=k;i++){
        scanf("%lld",a+i);
        if(a[i]%2==0)
            odd=0;
    }
    int all=2;
    for(int i=1;i<=k;i++)
        all=pow(all,a[i]%(mod-1));
    if(odd)printf("%lld/%lld\n",(ll)(all-2+mod)%mod*inv3%mod*inv2%mod,(ll)all*inv2%mod);
    else printf("%lld/%lld\n",(ll)(all+2)*inv3%mod*inv2%mod,(ll)all*inv2%mod);
    return 0;
}