记录编号 133523 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2012]Contra 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 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;
}