hdu4043FXTZ II(大数+数学)

/*hdu4043FXTZ II

(引用)

题意:A、B两人初始血量相同,有n个技能,伤害分别为^i(i=,,,…,n-1),每随机(机会均等)选择一个技能随机(机会均等)打向A或B,直到技能用完,每个技能只被选择一次,且每次攻击后A的血量只要有一次超过B的血量,则A赢B输,问B赢的概率是多少。要求用最简分数表示。

思路:

当n=1时,p1 = 1/2

当n=2时,第一个技能伤害如果是,只要第一个打出的技能打向A,则B必胜,这个事件发生的概率为/2 * 1/2;第一个如果是,那么只有两技能都打向A,B才能胜,事件发生的概率为/2 * 1/2 * 1/2;.则p2 =1/4 + 1/8 = 3/8

当n=3时,伤害为的技能如果为第一个技能,只要打向A,则B必胜,发生的概率为/3 * 1/2;如果为第二个技能,则前一个技能和这个技能必须都打向A,B才能胜,概率为/3 * 1/2 * 1/2;如果为第三个技能,则前两可如当n=2时的概率且第三个技能必须打向A,B才能,概率为/3 * 3/8 *1/2.则

p3=1/3 * (1 + p1 + p2) * 1/2.

同理,p4 = 1/4 * (1 + p1 + p2 + p3) * 1/2

则pn = 1/(2 * n) * (1 + p1 + p2 + …+ pn).

由上式可推得pn = p(n-1) * (2 * n - 1)/(2 * n)(以下代码即用此式解答),

如果继续推,可推得pn = A(2n , n)/( 2^(2n) * n! )(其中,A(2n , n)为排列式)。

*/

View Code
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
#define MAXN 555
string fa[MAXN],fb[MAXN];


bool operator>=(const string &a,const string &b)
{
if(a.size()>b.size())return true;
if(a.size()==b.size()&&a>b)return true;
if(a==b)return true;
return false;
}
string sub(const string &a,const string &b)//大数减法模板
{
if(a==b)return "0";
string s(a);
for(int bi=b.size()-1,si=s.size()-1;si>=0;si--,bi--)
if((s[si]-=(bi>=0? b[bi]-'0' : 0))<'0')
s[si]+=10,s[si-1]--;
return s.substr(s.find_first_not_of('0'));
}

string operator *(const string &a,int b)//大数*int
{
int tmp=0;
string c="";
for(int ci=0,i=a.size()-1;i>=0;i--,ci++)
{
tmp+=(a[i]-'0')*b;
c+=tmp%10+'0';
tmp/=10;
}
while(tmp)
{
c+=tmp%10+'0';
tmp/=10;
}
reverse(c.begin(),c.end());
return c;
}
string operator %(const string &a,const string &b)//大数取余
{
string s,c;
c=a.substr(0,b.size()-1);
for(int i=b.size()-1;i<a.size();i++)
{
int cnt=0;
for(c=(c=="0"?string():c)+a[i];c>=b;cnt++)
c=sub(c,b);
s+=char(cnt+'0');
}
return c;
}
string operator /(const string &a,const string &b)//大数除法
{
string s,c;
c=a.substr(0,b.size()-1);
for(int i=b.size()-1;i<a.size();i++)
{
int cnt=0;
for(c=(c=="0"?string():c)+a[i];c>=b;cnt++)
c=sub(c,b);
s+=char(cnt+'0');
}
return s[0]=='0'?s.substr(1):s;
}
string gcd(string a,string b)//大数求最大公约数
{
string c;
if(a=="0")return b;
while(b!="0"){c=b,b=a%b,a=c;}
return a;
}
void pro()
{
fa[1]="1";
fb[1]="2";
for(int i=2;i<=500;i++)
{
fa[i]=fa[i-1]*(2*i-1);
fb[i]=fb[i-1]*2*i;
}
}
int main()
{
int cas,n;
string c;
pro();
scanf("%d",&cas);
while(cas--)
{
cin>>n;
c=gcd(fa[n],fb[n]);
fa[n]=fa[n]/c;
fb[n]=fb[n]/c;
cout<<fa[n]<<"/"<<fb[n]<<endl;
}
}

 

原文地址:https://www.cnblogs.com/sook/p/2228242.html