2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin(构造二项式定理 or dp矩阵优化)

来源:互联网 发布:java.util.calendar 编辑:程序博客网 时间:2024/05/31 11:04


题目链接
题意:

一枚硬币,投一次正面朝上概率为q/p, 求投k次,正面朝上的次数为偶数次的概率X/Y,输出(XY1)mod(1e9+7)

思路:

观察发现所有可能的次数,是一个二项式定理展开式,
这里写图片描述
所以我们构造一个 (p/q)x+(pq)/pk 可以发现我们首先将x赋值为1,那么全部为正的,然后再将x赋值为-1,发现奇数项系数为-。那么二者相加 得到 公式为:
(1+((p2q)/p)k)/2
题中满足 p>= 2q;

#include<bits/stdc++.h>  using namespace std;  const int mod = 1e9+7;  typedef long long ll;  ll p, q, n;  ll qmod(ll x, ll q)  {      ll res = 1;      while(q)      {          if(q%2) res = res*x%mod;          x = x*x%mod;          q /= 2;      }      return res;  }  int main(void)  {      int _;      cin >> _;      while(_--)      {          scanf("%lld%lld%lld", &p, &q, &n);          ll ni2 = qmod(2LL, mod-2);          ll fm = qmod(p, n);          ll fz = qmod(p-2*q, n);          ll nifm = qmod(fm, mod-2);          ll tmp = (1+fz*nifm%mod)%mod*ni2%mod;          printf("%lld\n", tmp);      }      return 0;  }  

另外也可以dp,首先设dp[i][1]表示投i次满足偶数次正面朝上,dp[i][2]表示奇数次,那么有
dp[i][1] = 上*dp[i-1][2]+下*dp[i-1][1]
dp[i][2] = 上*dp[i-1][1]+下*dp[i-1][2]

#include <iostream>  #include <stdlib.h>  #include <string.h>  #include <stdio.h>  #include <queue>  #include <algorithm>  using namespace std;  typedef long long ll;  const int maxn=3;  struct Matrix{    ll a[maxn][maxn];    void init()              {      memset(a,0,sizeof(a));      for(int i=1;i<maxn;i++)        a[i][i]=1;    }  }  ;  const ll mod=1000000007;  Matrix mul(Matrix a,Matrix b)   {    Matrix ans;    memset(ans.a,0,sizeof(ans.a));    for(int i=1;i<maxn;i++)      for(int j=1;j<maxn;j++)      {        ans.a[i][j]=0;        for(int k=1;k<maxn;k++)          {              ans.a[i][j]+=a.a[i][k]*b.a[k][j] ;              ans.a[i][j]%=mod;          }      }      return ans;  }  Matrix pow(Matrix a,ll m)  {      Matrix res ;      memset(res.a,0,sizeof(res.a));      for(int i=1;i<maxn;i++)      {          res.a[i][i]=1;      }      while(m)      {          if(m&1)          {              res=mul(a,res);          }          a=mul(a,a);          m/=2;      }      return res;  }  ll quick(ll n,ll m)  {      ll ans = 1;      while(m){          if(m & 1)              ans = ans * n % mod;          m >>= 1;          n = n * n % mod;      }      return ans;  }  int main()  {      double p;      int t=0;      int n;      scanf("%d",&t);      while(t--)      {          ll p,q,k;          scanf("%lld%lld%lld",&p,&q,&k);          ll nums=    q*quick(p,mod-2)%mod;          ll numx=(p-q)*quick(p,mod-2)%mod;          Matrix ans;          ans.a[1][1]=(numx)%mod;          ans.a[2][1]=(nums)%mod;           if(k==1)          {              printf("%lld\n",ans.a[1][1]%mod);              continue;          }          Matrix base,res;          base.a[1][1]=numx,base.a[1][2] =nums;          base.a[2][1]=nums,base.a[2][2]= numx;          res=pow( base, k - 1 );          ans=mul( base,res);          printf("%lld\n",ans.a[1][1]%mod);      }  }  
阅读全文
0 0
原创粉丝点击