2943 射箭 1
甲乙两人去射箭,采用轮流制(甲乙甲乙……),谁先射中谁获得胜利,已知甲的命中率为,乙的命中率为,求乙获得胜利的概率。
共一行,四个用空格隔开的正整数。保证。
共一行,一个小数,表示乙的胜率,四舍五入强制保留1000位小数。
1 2 7 23
0.2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
对于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);
}
代码