P2236

[HNOI2002]彩票

题目描述

某地发行一套彩票。彩票上写有 \(1\)\(M\)\(M\) 个自然数。彩民可以在这 \(M\) 个数中任意选取 \(N\) 个不同的数打圈。每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同。

每次抽奖将抽出两个自然数 \(X\)\(Y\)。如果某人拿到的彩票上,所选 \(N\) 个自然数的倒数和,恰好等于 \(\dfrac{X}{Y}\),则他将获得一个纪念品。

已知抽奖结果 \(X\)\(Y\)。现在的问题是,必须准备多少纪念品,才能保证支付所有获奖者的奖品。

输入格式

输入文件有且仅有一行,就是用空格分开的四个整数 \(N\)\(M\)\(X\)\(Y\)

输出格式

输出文件有且仅有一行,即所需准备的纪念品数量。

样例 #1

样例输入 #1

2 4 3 4

样例输出 #1

1

提示

\(1 \leq X, Y \leq 100\)\(1 \leq N \leq 10\)\(1 \leq M \leq 50\)

输入数据保证输出结果不超过 \(10^5\)

DFS+剪枝
首先 精度!
这题eps要取1e-10
然后有个警示自己的地方:
最开始我是这么写的:
点击查看代码
void dfs(int pre,double tot,int cnt)//上一个选的数 总和 选了几个 
{
	if(cnt==n+1)
	{
		if(fabs(tot-ans)<eps)minn++;
		if(minn>100000)
		{
			cout<<minn<<"\n";
			exit(0);
		}
		return ;
	}
	if(tot+(double)(n-cnt)/(double)(m)>ans+eps)return ;
	if(tot+(double)(n-cnt)/(double)(pre+1)<ans-eps)return ;
	for(int i=pre+1;i<=m;i++)
	{
		if(tot+1.0/(double)i<ans-eps||fabs(tot+1.0/(double)i-ans)<eps)
		dfs(i,tot+1.0/(double)i,cnt+1);
	}
}

出问题是因为我的cnt不是真正的cnt!所以剪枝那块就完全错了一位!
✔写法
点击查看代码
void dfs(int pre,double tot,int cnt)//上一个选的数 总和 选了几个 
{
	if(tot>ans+eps)return ;
	if(cnt==n)
	{
		if(fabs(tot-ans)<eps)minn++;
		if(minn>100000)
		{
			cout<<minn<<"\n";
			exit(0);
		}
		return ;
	}
	if(tot+(double)(n-cnt)/(double)(m)>ans+eps)return ;
	if(tot+(double)(n-cnt)/(double)(pre+1)<ans-eps)return ;
	for(int i=pre+1;i<=m;i++)
	{
		if(tot+1.0/(double)i<ans-eps||fabs(tot+1.0/(double)i-ans)<eps)
		dfs(i,tot+1.0/(double)i,cnt+1);
	}
}
整个的代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
double ans;
int n,m,x,y,minn=0;
void dfs(int pre,double tot,int cnt)//上一个选的数 总和 选了几个 
{
	if(tot>ans+eps)return ;
	if(cnt==n)
	{
		if(fabs(tot-ans)<eps)minn++;
		if(minn>100000)
		{
			cout<<minn<<"\n";
			exit(0);
		}
		return ;
	}
	if(tot+(double)(n-cnt)/(double)(m)>ans+eps)return ;
	if(tot+(double)(n-cnt)/(double)(pre+1)<ans-eps)return ;
	for(int i=pre+1;i<=m;i++)
	{
		if(tot+1.0/(double)i<ans-eps||fabs(tot+1.0/(double)i-ans)<eps)
		dfs(i,tot+1.0/(double)i,cnt+1);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>x>>y;
	ans=(double)x/(double)y;
	dfs(0,0.0,0);
	cout<<minn<<"\n";
	return 0;
}
posted @ 2023-01-16 19:23  PKU_IMCOMING  阅读(18)  评论(0)    收藏  举报