【ASC45D】【构造 电阻网络法+暴力冲精度法+比例转换法】醉汉走路二分叉 回家概率恰为p/q

55 篇文章 0 订阅
24 篇文章 0 订阅

【ASC45D】【构造】方法一之电阻网络法 WIKI Gambler's ruin

#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional> 
#include<string>
#include<algorithm>
#include<time.h>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=0,M=0,L=0,Z=1e9+7,t30=1<<30,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
const double eps=1e-8,PI=acos(-1.0);//.0
struct A{};
map<int,int>mop;
int casenum,casei,inf;
int p,q;//概率为p/q
int a[105];
int b[105][2];
void fre()
{
	freopen("drunkard.in","r",stdin);
	freopen("drunkard.out","w",stdout);
}
int main()
{
	fre();
	while(~scanf("%d%d",&p,&q),p||q)
	{
		//n,p-1个中转点,1,q-p-1个中转点,n-1
		//即q+1,[2,p],1,[p+1,p+q-p-1],q
		printf("%d\n",q+1);
		int m=0;
		a[++m]=q+1;
		for(int i=2;i<=p;i++)a[++m]=i;
		a[++m]=1;
		for(int i=p+1;i<=q;i++)a[++m]=i;
		for(int i=2;i<m;i++)
		{
			b[a[i]][0]=a[i-1];
			b[a[i]][1]=a[i+1];
		}
		for(int i=1;i<=m-2;i++)printf("%d %d\n",b[i][0],b[i][1]);
	}
	return 0;
}
/*
【题意】
一个醉汉在一个有向图上走。
该有向图有n个点,除了第n-1和第n个点,每个点都有两条出边,可以有重边,可以有自环。
我们从1点开始走,每次等概率选择两条出边中的一条走,走到n或者n-1就停下。
已知这个人走到n-1号点的概率是p/q,现在问你这个图可以是怎样的。

题目只告诉你p和q。
n以及1~n-2的每个点连出的边都是你自己定的。
[1<=p<q<=100],[1<=n<=1000]

【类型】
构造题,脑洞题

【分析】
我们想构造出p/q的概率,要既能恰好达成分母,又能恰好达成分子。
首先最基本的大概是一条链,每个点发出两条边都相同。
这样我们可以有50/100的概率到达n-1
比如1->2->3->4->
             |
			 n-1

但是链结构的话,我们很难使得分母恰好符合要求。
于是我们可以考虑二叉树结构。
二叉树可以分出2^m个节点,使得2^m>=q。

但是这样要如何构成恰好的分数呢?比如1/3?
这时就知道先看样例的重要性了。样例中就恰好是1/3——
4<-1<->2->3

这里存在环结构,于是我们设想通过列方程求解。
我们设达到点x的概率为p[x],那么就有——
p[1]=1,
p[2]=0.5p[1]
p[1]=0.5p[2]
=========================================================
ICPC的大神告诉了我一种构造方法。
思想类似于电阻网络:
n,p-1个中转点,1,q-p-1个中转点,n-1
为什么这样构造是对的呢QwQ不太理解。
=========================================================
精度逼近法是否可以尝试呢?

【优化】

【trick】

【数据】
input
1 3
0 0

output
4
2 4
3 1

*/

【ASC45D】【构造】方法二之暴力冲精度法

#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional> 
#include<string>
#include<algorithm>
#include<time.h>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=0,M=0,L=0,Z=1e9+7,t30=1<<30,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
int p,q;//概率为p/q
struct A
{
	int l,r;
	double u;
}a[1000];
void fre()
{
	freopen("drunkard.in","r",stdin);
	freopen("drunkard.out","w",stdout);
}
int main()
{
	fre();
	while(~scanf("%d%d",&p,&q),p||q)
	{
		double v=1.0*p/q;
		double u=1;
		for(int i=1;i<=998;i++)
		{
			a[i].l=i+1;//链上都是奇数点——1,3,5,7,9,...
			a[i].r=1000;//结束点初始都设为n。
			a[i].u=u=u/2;
		}
		for(int i=1;i<=998;i++)
		{
			if(v>=a[i].u)
			{
				a[i].r=999;
				v-=a[i].u;
			}
		}
		printf("%d\n",1000);
		for(int i=1;i<=998;i++)
			printf("%d %d\n",a[i].l,a[i].r);
	}
	return 0;
}
/*
【题意】
一个醉汉在一个有向图上走。
该有向图有n个点,除了第n-1和第n个点,每个点都有两条出边,可以有重边,可以有自环。
我们从1点开始走,每次等概率选择两条出边中的一条走,走到n或者n-1就停下。
已知这个人走到n-1号点的概率是p/q,现在问你这个图可以是怎样的。

题目只告诉你p和q。
n以及1~n-2的每个点连出的边都是你自己定的。
[1<=p<q<=100],[1<=n<=1000]

【类型】
构造题,脑洞题

【分析】
我们想构造出p/q的概率,要既能恰好达成分母,又能恰好达成分子。
首先最基本的大概是一条链,每个点发出两条边都相同。
这样我们可以有50/100的概率到达n-1
比如1->2->3->4->
             |
			 n-1

但是链结构的话,我们很难使得分母恰好符合要求。
于是我们可以考虑二叉树结构。
二叉树可以分出2^m个节点,使得2^m>=q。

但是这样要如何构成恰好的分数呢?比如1/3?
这时就知道先看样例的重要性了。样例中就恰好是1/3——
4<-1<->2->3

这里存在环结构,于是我们设想通过列方程求解。
我们设达到点x的概率为p[x],那么就有——
p[1]=1,
p[2]=0.5p[1]
p[1]=0.5p[2]
=========================================================
ICPC的大神告诉了我一种构造方法。
思想类似于电阻网络:
n,p-1个中转点,1,q-p-1个中转点,n-1
为什么这样构造是对的呢QwQ不太理解。
=========================================================
精度逼近法是否可以尝试呢?
竟然也AC啦!
果然有时候大力出奇迹啊!出题人还是普遍懒啊!

【优化】

【trick】

【数据】
input
1 3
0 0

output
4
2 4
3 1

*/

【ASC45D】【构造】方法三之比例转换法

#include<stdio.h> 
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional> 
#include<string>
#include<algorithm>
#include<time.h>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=0,M=0,L=0,Z=1e9+7,t30=1<<30,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
int p,q;//概率为p/q
struct A
{
	int l,r,u;
}a[20];
void fre()
{
	freopen("drunkard.in","r",stdin);
	freopen("drunkard.out","w",stdout);
}
int main()
{
	fre();
	while(~scanf("%d%d",&p,&q),p||q)
	{
		q=q-p;
		a[1].l=2;a[1].r=9;
		for(int i=2,u=128;i<=8;i++)
		{
			a[i].l=i+1;
			a[i].r=1;
			a[i].u=u=u>>1;
		}a[8].l=1;
		for(int i=9,u=128;i<=15;i++)
		{
			a[i].l=i+1;
			a[i].r=1;
			a[i].u=u=u>>1;
		}a[15].l=1;

		for(int i=2;i<=8;i++)
		{
			if(p>=a[i].u)
			{
				a[i].r=16;
				p-=a[i].u;
			}
		}
		for(int i=9;i<=15;i++)
		{
			if(q>=a[i].u)
			{
				a[i].r=17;
				q-=a[i].u;
			}
		}
		printf("17\n");
		for(int i=1;i<=15;i++)printf("%d %d\n",a[i].l,a[i].r);
	}
	return 0;
}
/*
【题意】
一个醉汉在一个有向图上走。
该有向图有n个点,除了第n-1和第n个点,每个点都有两条出边,可以有重边,可以有自环。
我们从1点开始走,每次等概率选择两条出边中的一条走,走到n或者n-1就停下。
已知这个人走到n-1号点的概率是p/q,现在问你这个图可以是怎样的。

题目只告诉你p和q。
n以及1~n-2的每个点连出的边都是你自己定的。
[1<=p<q<=100],[1<=n<=1000]

【类型】
构造题,脑洞题

【分析】
我们想构造出p/q的概率,要既能恰好达成分母,又能恰好达成分子。
首先最基本的大概是一条链,每个点发出两条边都相同。
这样我们可以有50/100的概率到达n-1
比如1->2->3->4->
             |
			 n-1

但是链结构的话,我们很难使得分母恰好符合要求。
于是我们可以考虑二叉树结构。
二叉树可以分出2^m个节点,使得2^m>=q。

但是这样要如何构成恰好的分数呢?比如1/3?
这时就知道先看样例的重要性了。样例中就恰好是1/3——
4<-1<->2->3

这里存在环结构,于是我们设想通过列方程求解。
我们设达到点x的概率为p[x],那么就有——
p[1]=1,
p[2]=0.5p[1]
p[1]=0.5p[2]
=========================================================
ICPC的大神告诉了我一种构造方法。
思想类似于电阻网络:
n,p-1个中转点,1,q-p-1个中转点,n-1
为什么这样构造是对的呢QwQ不太理解。
=========================================================
精度逼近法是否可以尝试呢?
竟然也AC啦!
果然有时候大力出奇迹啊!出题人还是普遍懒啊!
=========================================================
这题还有另外一种做法,就是比例转换法。
我们想,如果是有p/2^k流向了n-1节点,有(q-p)/2^k流向了n节点,有(2^k-q)/2^k的流回根。答案肯定也可以。
于是做法是,依然构建一个二叉树结构的图。
	root
	|	|
	2	9
	3	10
	4	11
	5	12
	6	13
	7	14
	8	15

	16形成自环,表示dead节点
	17=n-1和18=n是需要流向的节点

左子树向n-1流动,右子树向n流动
对于每个子树,都可以流出1/4,1/8,...,1/2^k的流量。
如果k达到了256,我们就可以凑出(1~127)/256的比例是流向n-1的,使得分子恰好为p即可
同理,我们凑出q/256的比例是流向n
但是这样,走到n-1点的概率依旧是p/256,我们要消分母。
如果消除分母呢?我们把多余的流量流回根。
这样对于一个从根部开始展开的决策,能流出流量的概率就恰好是q/256,然后其中有(p-q)/q流向了n-1
于是这个构造方法可以AC这道题。

【优化】

【trick】

【数据】
input
1 3
0

output
4
2 4
3 1

*/


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值