• [FZYZOJ 1002] 雨天


    P1002 -- 雨天

    时间限制:1000MS      内存限制:65536KB无   无

    Description

    规则是这样的:每位姿迷可以抽到一张奖券。奖券上写有1到M这M个自然数。姿迷可以在这M个数中任意选取N个不同的数打圈。每个姿迷只能买一张奖券,不同的奖券上的选择不同。

    每次抽奖将抽出两个自然数X和Y。如果某人拿到的奖券上,所选N个自然数的倒数和,恰好等于X/Y,则他将免费获得一张CD《My Story Your Song》。 现在,已知抽奖结果X和Y。作为燕姿的fans,你的任务是:求出必须准备多少CD,才能保证支付所有获奖者。 对于所有数据,N<=12,M<=60 X<=25,Y<=25 且对于同一种选数,syz只用支付一盘CD

    Input Format

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

    Output Format

    输出有且仅有一行,即所需准备的CD数量。

    Sample Input

    2 4 3 4
    

    Sample Output

    1
    

    Hint

    好题!

    【题解】

    看到本题n、m、x、y都十分小,所以不需要使用分数类,直接用double,注意精度问题,判断相等用1e-9作为标准。

    而且呢,还可以直接搜索,但是原本搜索的时间复杂度的max为C(60,12),但是我们可以加入如下剪枝:

    1. 如果当前得到的数已经比x/y大,那么return

    2. 如果当前得到的数加上最大的数乘还剩下选的次数仍比x/y,那么return

    3. 如果当前得到的数加上最小的数乘还剩下选的次数仍比x/y,那么return

    第4条,也是重要的一条,大神讲的:

    4. 假设当前总和为a/b(a,b互质),那么a/b+1/p=(ap+b)/(bp),可知p一定会留在分母不能被约去,因为b一定不小于2,所以当p为比25大的质数时,1/p一旦被加入总和,分母便一定大于25,超过了题目y的范围。我们可以不予考虑这些质数;

    然后根据神牛的指导,发现了一些规律,呈现在代码里了

    = =其实我也没有弄懂|||

    然后就AC了,0.107s,还排前几名。orz

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 double tar;
     4 double eps = 1e-9;
     5 double minuseps = -eps;
     6 bool used[61];
     7 int cnt=0;
     8 int n,m,x,y;
     9 inline double fabs(double a) {return a>0?a:-a;}
    10 void tryy(int step, double now, int last) {
    11     //cout<<step<<' '<<now<<' '<<last<<endl; 
    12     if (step == n+1) {
    13         if (now<=eps&&now>=minuseps) cnt++;
    14         return ;
    15     }
    16     if (now <= minuseps) return;
    17     if (now - (n-step+1)*1.0/(last+1) >= eps) return; //printf("1");
    18     if (now - (n-step+1)*1.0/m <= minuseps) return; //printf("1");
    19     for (int i=last+1;i<=m;++i) if(used[i]) tryy(step+1, now-1.0/i, i);
    20     //printf("1");
    21 }
    22 int main() {
    23     scanf("%d%d%d%d",&n,&m,&x,&y);
    24     tar=1.0*x/y;
    25     memset(used,0,sizeof(used));
    26     for (int i=2;i<=sqrt(m);++i)
    27         if(!used[i]) for (int j=i*2;j<=m;j+=i) used[j]=1;
    28     for (int i=1;i<=11;++i) used[i]=true;
    29     used[25]=used[26]=used[27]=used[32]=used[34]=used[38]=used[39]=used[44]=used[46]=used[49]=used[50]=0;
    30     tryy(1,tar,0);
    31     printf("%d
    ",cnt);
    32     return 0;
    33 }
    View Code
    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    关于课程设计、毕业设计的一些总结与思考
    分享一个Panda C-60 维修心得
    未能加载文件或程序集“SuperMap.Data.dll”
    VS2017环境下安装AO10.2的方法
    SQL Server连接错误1326
    VMWare虚拟机中CPU过高的问题
    Apktool编译找不到“keyboardNavigationCluster”
    Aspose.Cells设置单元格格式
    谷歌Chrome浏览器无法安装插件的解决方法
    Global Mapper如何加载在线地图
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/fzyzoj1002.html
Copyright © 2020-2023  润新知