HDOJ 1099 Lottery
题目
点此查看 HDOJ 1099 Lottery
分类
找规律
模拟
题意
题意比较难理解
有 n张彩票(每张获得概率相同) 集齐可得将奖
求平均买几张 可得奖
非直译 参考 飞矢不动 的 帖子
题解
例如 3 张彩票 1,2,3
获得 第 1 张的概率 1
获得 第 2 张的概率 23 要获得第二张 则需要 123 次购买
同理 张数为 1+123+113
n 张的 张数 sum=1+1n−1n+1n−2n+...+11n=n∗(1n+1n−1+1(n−2)+...+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;
}