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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号