• 【省选模拟】—猎人杀(概率dp)


    加特林轮盘赌差别不大(虽然我没做过……)

    考场上想了一个利用树状图转移的n3n^3做法
    但是觉得写不出来就没做…

    实际上可以很简单的列出dpdp
    f[i][j]f[i][j]表示剩ii个人,第jj个人活下来的概率
    f[i][j]=(f[i1][j1]+f[i][jk])/2f[i][j]=(f[i-1][j-1]+f[i][j-k])/2
    发现这是带环的
    而且多个环相互独立的
    手动消元就可以了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    #define int long long
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    #define gc getchar
    const int mod=1e9+7,inv=5e8+4;
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    inline int add(int a,int b){
    	return a+b>=mod?a+b-mod:a+b;
    }
    inline int mul(int a,int b){
    	return a*b>=mod?a*b%mod:a*b;
    }
    inline int dec(int a,int b){
    	return a>=b?a-b:a-b+mod;
    }
    inline int ksm(int a,int b,int res=1){
    	for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;
    	return res;
    }
    const int N=2005;
    struct data{
    	int x,y;
    	data(int _x=0,int _y=0):x(_x),y(_y){}
    	friend inline data operator +(const data &a,const data &b){
    		return data(a.x+b.x,a.y+b.y);
    	}
    	friend inline data operator+(const data&a,const int&b){
    		return a+data(0,b);
    	}
    	friend inline data operator *(const data &a,int b){
    		return data(mul(a.x,b),mul(a.y,b));
    	}
    }g[N];
    bool vis[N];
    int f[N][N],k,idx[N];
    inline int pre(int i,int j){
    	return j==k?i:(j>k?j-k:j-k+i);
    }
    inline int nxt(int i,int j){
    	return j+k<=i?j+k:j+k-i;
    }
    inline void calc(int n,int m){
    	vis[m]=1,idx[1]=m;
    	if(m!=k)g[1]=data(inv,mul(inv,f[n-1][pre(n,m)]));
    	else g[1]=data(inv,0);
    	int p=nxt(n,m),pr=m,tim=2,x0;
    	while(!vis[p]){
    		idx[tim]=p,vis[p]=1;
    		if(p!=k)g[tim]=(g[tim-1]+f[n-1][pr])*inv;
    		else g[tim]=g[tim-1]*inv;
    		pr=p,p=nxt(n,p),++tim;
    	}
    	--tim;
    	x0=mul(g[tim].y,ksm(dec(1,g[tim].x),mod-2));
    	for(int i=1;i<=tim;i++)f[n][idx[i]]=add(mul(g[i].x,x0),g[i].y);
    }
    int n,K;
    signed main(){
    	n=read(),K=read();
    	f[1][1]=1;
    	for(int i=2;i<=n;i++){
    		memset(vis,0,sizeof(vis));
    		k=(K%i==0)?i:(K%i);
    		for(int j=1;j<=i;j++)if(!vis[j])calc(i,j);
    	}
    	cout<<f[n][1];
    }
    
  • 相关阅读:
    关于数组的一些面试题目及答案
    java类的定义以及参数传递
    第39届大学生程序设计大赛亚洲区域赛广州站比赛总结
    模拟退火法(吊打XXX)Bzoj3680
    树链剖分(单点更新,求区间最值,区间求和Bzoj1036)
    树链剖分(线段树区间更新求和(lazy操作)hdu3966)
    最大权闭合图(Road constructions)hdu3917
    最大权闭合图最大获益(把边抽象为点)HDU3879
    最大权闭合图hdu3996
    最大密集子图(01分数规划+二分+最小割)POJ3155
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145566.html
Copyright © 2020-2023  润新知