HDOJ HDU 1099 Lottery

HDOJ 1099 Lottery

题目

点此查看 HDOJ 1099 Lottery

分类

找规律
模拟

题意

题意比较难理解
有 n张彩票(每张获得概率相同) 集齐可得将奖
求平均买几张 可得奖
非直译 参考 飞矢不动 的 帖子

题解

例如 3 张彩票 1,2,3
获得 第 1 张的概率 1
获得 第 2 张的概率 23 要获得第二张 则需要 123 次购买
同理 张数为 1+123+113
n 张的 张数 sum=1+1n1n+1n2n+...+11n=n(1n+1n1+1(n2)+...+1)
公式得出
打表计算 1 + … + 1/n
化简 按 要求输出

技巧

由于问题输出要以分数形式
所以分数的分母和分子要分别输出
由于问题输出分数要最简形式
所以此题涉及约分问题
模拟 约分计算
我们要先将 两分母 乘上对应数 变成 最小公倍数 由于要保持分数不变 分子也要对应乘以 分母相乘的数 相加 即可
例如 23+45
求 3 和 5 的 最小公倍数 15
分母为 (2 * (15/3) + 4 * (15/5)) = 22
求最大公约数
我们可以先求 最大公约数 用 两数相乘 再除以最大公约数 即得到 最小公倍数
例如 9 6 的最大公倍数 为 9 * 6 / 3 = 18

给需要打表对拍的同学

1
3
  1
5 -
  2
  1
8 -
  3
   5
11 --
   12
   7
14 --
   10
   3
18 --
   20
   26
21 --
   35
   129
25 ---
   280
   73
29 ---
   252
   551
33 ----
   2520
   551
37 ----
   2310
   9473
41 -----
   27720
   13433
45 -----
   25740
   18581
49 -----
   24024
   4129
54 -----
   45045
   340463
58 ------
   720720
   620743
62 ------
   680680
   1662439
67 -------
   4084080
   3704479
71 -------
   3879876
   408335
76 ------
   739024
   46533
81 ------
   235144

代码

#include <iostream>
#include <sstream>
#define max 22

using namespace std;

//long z[max];
long fz[max];
long fm[max];

int ctn(long x);
long gcd(long a,long b);

int main()
{
    long t,n;
    fz[0] = 1;
    fm[0] = 1;
    for(int i = 1;i < max;i++)
    {
        t = gcd(fm[i-1],i+1);
        // t为最大公约数 
        fm[i] = fm[i-1] / t * (i+1);
        // fm[i] 为 最小公倍数
        fz[i] = (i+1) / t * fz[i-1]  + fm[i-1] /t;
        //对应求出分子
    }
    while(cin >> n)
    {
        if(n == 1)
        {
            cout << 1 << endl;
            continue; 
        } 
        if(n == 2)
        {
            cout << 3 << endl;
            continue; 
        }
        n--;
        t = fm[n] / (n+1);
        int ys = gcd(fz[n] % t,t);
        //算出的数分子分母没有到最简 
        //再找最大公约数划到最简
        if(n >= 4)
            cout << ' '; 
        cout << "  " << fz[n] % t / ys << endl;
        printf("%d ",fz[n] / t);
        int mn = ctn(t/ys);
        for(int i = 0;i < mn;i++)
            putchar('-');
        putchar('\n');
        if(n >= 4)
            cout << ' '; 
        cout << "  " << t / ys << endl;
    }
    return 0;
}

long gcd(long a,long b)
{
    return a % b == 0 ? b : gcd(b,a%b);
}

int ctn(long x)
{
//    cout << x << " x" << endl;
    int t = 1;
    while(x / 10 != 0)
    {
        x/=10;
        t++;
    }
    return t;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值