[HNOI 2002]彩票

Description

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

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

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

Input

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

Output

输出文件有且仅有一行,即所需准备的纪念品数量。 1≤X, Y≤100,1≤N≤10,1≤M≤50。输入数据保证输出结果不超过10^5。

Sample Input

2 4 3 4

Sample Output

1

题解

好早之前写的题解...代码写得丑

拿到这道题,第一个思路是以层数为关键词,搜索,

但惨痛的实践和教训的结论下,还是改用了以分母为关键词,考虑“选与不选”

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<string>
 7  using namespace std;
 8 const double MINN=1e-10;//浮点数计算有误差 
 9 int x,y,n,m;
10 double ans;
11 double pre[55];//预处理,前缀和 
12 int cnt;
13 void dfs(int cen,int first,double tol)//当前第cen层,从first开始循环,当前总和为tol 
14 {
15     double minn=tol+pre[m]-pre[m-(n-cen)];//tol加上未计算最小的和 
16     double maxn=tol+pre[first+(n-cen)]-pre[first];//tol加上未计算最大的和 
17     if (minn-ans>MINN||maxn-ans<-MINN) return;//判断过多或过少的条件 
18     if (cen>=n)
19     {
20         cnt++;
21         return;
22     }
23     if (cen>=n) return;
24     dfs(cen,first+1,tol); 
25     dfs(cen+1,first+1,tol+1.0/(first+1));//考虑当前选与不选 
26     return;
27 }
28 int main()
29 {
30     scanf("%d%d%d%d",&n,&m,&x,&y);
31     ans=(double)x/(double)y;
32     for (int i=1;i<=m;i++)
33         pre[i]=pre[i-1]+1.0/(double)(i);
34     dfs(0,0,0);
35     printf("%d\n",cnt);
36     return 0;
37 }

 

posted @ 2017-09-01 16:08  NaVi_Awson  阅读(302)  评论(0编辑  收藏  举报