您的位置:首页 > 其它

codevs 2943 射箭 1--等比数列求和+高精度模板

2015-12-24 13:47 197 查看


2943 射箭 1

题目描述 Description

  甲乙两人去射箭,采用轮流制(甲乙甲乙……),谁先射中谁获得胜利,已知甲的命中率为

,乙的命中率为

,求乙获得胜利的概率。

输入描述 Input Description

  共一行,四个用空格隔开的正整数

。保证



输出描述 Output Description

  共一行,一个小数,表示乙的胜率,四舍五入强制保留1000位小数。

样例输入 Sample Input

1 2 7 23


样例输出 Sample Output

0.2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333


数据范围及提示 Data Size & Hint

  对于100%的数据:




算法分析:

等比数列求和,乙第一回合赢得几率,a1=(1-a/b)*(c/d),以后的等比系数q=(1-a/b)*(1-c/d),总的通项为a1/(1-q),化简后为(c*(b-a))/(a*d-c*(b-a)),

得到的结果一定为小数,所以将分子扩大1002倍后整除,根据最后一位处理进位。

定义大整数结构,重载=,-=,+=,*=。/=,+,-,*,/等,包括高精度*单精度,高精度/单精度,高精度*高精度,高精度/高精度。

#include<cstdio>

#include<cstring>

#include<algorithm>

#define REP(I,start,end) for(int I=start;I<=end;I++)

#define PER(I,start,end) for(int I=start;I>=end;I--)

using namespace std;

long long tmp[2100];

struct bigNumber{//定义大整数结构

int len;

long long num[2100];

inline void operator =(long long T){//重载=

memset(num,0,sizeof(num));

len=0;

while(T){

num[++len]=T%10;

T/=10;

}

}

inline bool operator >(const bigNumber T)const{//重载>

if(len<T.len)return false;

if(len>T.len)return true;

PER(ii,len,1){

if(num[ii]<T.num[ii])return false;

if(num[ii]>T.num[ii])return true;

}

return false;

}

inline void operator +=(const bigNumber T){//重载+=高精度+高精度

len=max(len,T.len);

REP(ii,1,len){

num[ii]+=T.num[ii];

num[ii+1]+=num[ii]/10;

num[ii]%=10;

}

while(num[len+1]){

len++;

num[len+1]+=num[len]/10;

num[len]%=10;

}

}

inline void operator -=(const long long TT){//重载-=高精度-单精度

long long T=TT;

int ii=1;

while(T){

num[ii]-=T%10;

T/=10;

ii++;

}

REP(ii,1,len)

while(num[ii]<0){

num[ii+1]--;

num[ii]+=10;

}

while(num[len]==0)

len--;

}

inline void operator *=(const long long T){//重载*=高精度*单精度

REP(ii,1,len)

num[ii]*=T;

REP(ii,1,len){

num[ii+1]+=num[ii]/10;

num[ii]%=10;

}

while(num[len+1]){

len++;

num[len+1]+=num[len]/10;

num[len]%=10;

}

}

inline void operator /=(const bigNumber T){////重载、=高精度/高精度

memset(tmp,0ll,sizeof(tmp));

int jj=len,tl=len;//jj,a.len tl,t.len

len=0; //len c.len商的位数

while(true){

while(tl<=jj){

int jjj=jj,kkk=T.len;

while(kkk&&num[jjj]==T.num[kkk]){

jjj--;

kkk--;

}

if(kkk&&num[jjj]<T.num[kkk])

jj--;

else

break;

}

if(jj<T.len)

break;

REP(ii,jj-T.len+1,jj){//找到第一个可以放商的位置 ,jj-T.len+1

num[ii]-=T.num[ii+T.len-jj];//减去一个除数

if(num[ii]<0){

num[ii+1]--;

num[ii]+=10;

}

}

tmp[jj-T.len+1]++;//商加1;

while(tl&&num[tl]==0)//去掉T的前置0;

tl--;

len=max(len,jj-T.len+1);

}

REP(ii,1,len)

num[ii]=tmp[ii];

}

}a,b,c,d;//?????a,b

inline bigNumber operator +(const bigNumber A,const bigNumber B){//重载+ 高精度+高精度

bigNumber C;

memset(C.num,0,sizeof(C.num));

C.len=max(A.len,B.len);

REP(ii,1,C.len)

C.num[ii]=A.num[ii]+B.num[ii];

REP(ii,1,C.len){

C.num[ii+1]+=C.num[ii]/10;

C.num[ii]%=10;

}

while(C.num[C.len+1]){

C.len++;

C.num[C.len+1]+=C.num[C.len]/10;

C.num[C.len]%=10;

}

return C;

}

inline bigNumber operator -(const bigNumber A,const bigNumber B){//重载- 高精度-高精度

bigNumber C;

memset(C.num,0,sizeof(C.num));

C.len=max(A.len,B.len);

REP(ii,1,C.len)

C.num[ii]=A.num[ii]-B.num[ii];

REP(ii,1,C.len){

if(C.num[ii]<0){

C.num[ii]+=10;

C.num[ii+1]-=1;

}

}

while(C.len>1&&C.num[C.len]==0)

C.len--;

return C;

}

inline bigNumber operator *(const bigNumber A,const bigNumber B){//重载* 高精度*高精度

bigNumber C;

memset(C.num,0,sizeof(C.num));

C.len=A.len+B.len-1;

REP(ii,1,A.len)

REP(jj,1,B.len)

C.num[ii+jj-1]+=A.num[ii]*B.num[jj];

REP(ii,1,C.len){

C.num[ii+1]+=C.num[ii]/10;

C.num[ii]%=10;

}

while(C.num[C.len+1]){

C.len++;

C.num[C.len+1]+=C.num[C.len]/10;

C.num[C.len]%=10;

}

return C;

}

inline void print(const bigNumber T){

if(T.len==0){

printf("0");

return;

}

PER(ii,T.len,1)

printf("%lld",T.num[ii]);

printf("\n");

}

inline long long operator %(const bigNumber A,const long long B){//重载% 高精度%单精度

long long T=0ll;

printf("T=%d\n",T);

PER(ii,A.len,1)

T=(T*10+A.num[ii])%B;

return T;

}

inline bigNumber operator /(const bigNumber A,const long long B){//高精度/单精度

long long T=0ll;

bigNumber C;

memset(C.num,0ll,sizeof(C.num));

C.len=A.len;

PER(ii,A.len,1){

T=(T*10+A.num[ii]);

C.num[ii]=T/B;

T=T%B;

}

while(C.len>1&&C.num[C.len]==0)C.len--;

return C;

}

inline bigNumber operator /( bigNumber A,const bigNumber B){//高精度/高精度

memset(tmp,0ll,sizeof(tmp));

bigNumber C,D;

int ii,jj=A.len,tl=A.len,len;//jj,A.len tl,余数的长度

D.len=B.len;

len=0; //len c.len商的位数

while(true){

/*//从被除数的左侧找到减去除数的数字段。

while(tl<=jj){//jj代表被除数左指针的位置

int jjj=jj,kkk=B.len;

while(kkk&&A.num[jjj]==B.num[kkk]){

jjj--;

kkk--;

}

if(kkk&&A.num[jjj]<B.num[kkk])//比较两数字大小,准备最高位的借位

jj--;

else

break;

}

*/

jj=tl;//第二种方法,从被除数的左侧找到减去除数的数字段。

D.len=B.len;

memcpy(D.num+1,A.num+(tl-B.len+1),8*B.len);

if(B>D)jj--;

if(jj<B.len)//除法结束

break;

REP(ii,jj-B.len+1,jj){//找到下一个可以放商的位置 ,jj-T.len+1

A.num[ii]-=B.num[ii+B.len-jj];//减去一个除数

if(A.num[ii]<0){//处理借位

A.num[ii+1]--;

A.num[ii]+=10;

}

}

tmp[jj-B.len+1]++;//商加1;商的第几位jj-T.len+1

while(tl&&A.num[tl]==0)//去掉被除数减后的前置0;

tl--;

len=max(len,jj-B.len+1);//记录商的最高位

}

REP(ii,1,len)

C.num[ii]=tmp[ii];

C.len=len;

return C;

}

inline bigNumber sqr(const bigNumber T){

return T*T;

}

bigNumber power(const bigNumber A,const int B){

if(B==1)

return A;

if(B%2)

return sqr(power(A,B>>1))*A;

return power(A,B>>1);

}

inline bigNumber fact(int n){

bigNumber ans;

ans=1ll;

REP(ii,2,n)

ans*=ii;

return ans;

}

inline bigNumber max(const bigNumber A,const bigNumber B){

if(A>B)

return A;

return B;

}

inline void scan(bigNumber& T){

memset(T.num,0,sizeof(T.num));

T.len=0;

char ch=getchar();

while(ch<'0'||ch>'9')

ch=getchar();

if(ch=='0'){

ch=getchar();

if(ch<'0'||ch>'9')

return;

}

while(ch=='0')

ch=getchar();

while(ch>='0'&&ch<='9'){

T.num[++T.len]=ch-'0';

ch=getchar();

}

if(T.len==1&&T.num[1]==0){

T.len=0;

return;

}

REP(ii,1,T.len>>1)

swap(T.num[ii],T.num[T.len-ii+1]);

}

int main()

{freopen("in.txt","r",stdin);

scan(a);

scan(b);

scan(c);

scan(d);

bigNumber ba,cba,ad,fm,fz,
maxfz;

ba=b-a;

fz=c*ba;

ad=a*d;

fm=ad+fz;

memset(a.num,0,sizeof(a.num));

a.len=1002;

a.num[1002]=1;

maxfz=fz*a;

b=maxfz/fm;

memset(a.num,0,sizeof(a.num));

a.len=2;

a.num[2]=1;

if(b.num[1]>4)b+=a;

int t=1001-b.len;

printf("0.");

int ans=0;

while(t>0){

printf("0");

ans++;

t--;

}

for(int i=b.len;i>1;i--){

ans++;

printf("%lld",b.num[i]);

}

// printf("%d \n",ans);

}

代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: