记录编号 |
133523 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[国家集训队2012]Contra |
最终得分 |
100 |
用户昵称 |
cstdio |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.861 s |
提交时间 |
2014-10-28 09:36:24 |
内存使用 |
0.31 MiB |
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int SIZE_MT=40;
class MATRIX{
public:
int n,m;
double s[SIZE_MT][SIZE_MT];
void clear(int a,int b){n=a,m=b;for(int i=0;i<a;i++){for(int j=0;j<b;j++){s[i][j]=0;}}}
void clearunit(int a){clear(a,a);for(int i=0;i<a;i++) s[i][i]=1;}
};
MATRIX operator * (MATRIX a,MATRIX b){
MATRIX c;
c.n=a.n,c.m=b.m;
for(int i=0;i<c.n;i++)
for(int j=0;j<c.m;j++){
c.s[i][j]=0;
for(int k=0;k<a.m;k++)
c.s[i][j]+=a.s[i][k]*b.s[k][j];
}
return c;
}
MATRIX quickpow(MATRIX a,int n){
MATRIX ans;ans.clearunit(a.n);
while(n){
if(n&1) ans=ans*a;
a=a*a;
n>>=1;
}
return ans;
}
pair<int,int> states[SIZE_MT];int stot;
//其中first是u值,second是生命值
int N,R,Q;
double S;
int findstate(int u,int q){
return find(states+1,states+stot+1,make_pair(u,q))-states;
}
MATRIX transfer(double p){//过关概率为p
MATRIX D;
//0是ans
D.clear(stot+1,stot+1);
//D.s[i][j]代表每次转移时i对之后的j的贡献系数
D.s[0][0]=1;
for(int i=1;i<=stot;i++){
int u=states[i].first,q=states[i].second;
//过了则u++,q++
D.s[i][findstate(min(u+1,R),min(q+1,Q))]=p;
D.s[i][0]=p*min(u+1,R);
//不过则u=0,q--
if(q-1) D.s[i][findstate(0,q-1)]=1-p;
}
return D;
}
double calc(double p){
MATRIX D=transfer(p);
MATRIX O;O.clear(1,stot+1);
O.s[0][findstate(0,Q)]=1;
O=O*quickpow(D,N);
return O.s[0][0];
}
void work(void){
if(calc(1.0)<=S){
printf("Impossible.\n");
return;
}
double l=0,r=1.0;
int tot=0;
while(tot++<30){
double mid=(l+r)/2;
if(calc(mid)>=S) r=mid;
else l=mid;
}
printf("%.6lf\n",l);
}
void make_states(void){//给合法状态打一张表
stot=0;
for(int u=0;u<=R;u++){
//此时生命值>=u+1
for(int j=min(u+1,Q);j<=Q;j++) states[++stot]=make_pair(u,j);
}
}
int main(){
freopen("nt2012_contra.in","r",stdin);
freopen("nt2012_contra.out","w",stdout);
cin>>N>>R>>Q>>S;
make_states();
work();
return 0;
}