Uniform Generator (hdu1014数论随即数)

本文讨论了随机数生成算法中循环节的性质,通过两种方法判断给定的STEP和MOD参数是否能形成良好的循环节,以及如何判断循环节的长度。详细解释了循环节形成的原因和判断条件。

题意: 随机数 seed(x+1) = [seed(x) + STEP] % MOD

如果 STEP = 3,MOD = 5 循环节 0,3,1,4,2,正好满足了随机数0~4随机循环,说明这个选择为 Good Choice

如果 STEP = 15,MOD = 30 循环节 0, 15, 10, 5,没有满足随机数0~29循环,说明这个选择为Bad Choice

现在给你 STEP 和 MOD 判断是 Good Choice 或者Bad Choice

第一种解法 暴力

思路:以为在0~~~MOD-1的随机数,所以只要循环MOD-1次就可以了,如果中间重复,就是Bad Choice,如果没出现说明Good Choice

因为 有一个数重复,那么必然后面的数都重复,所以只要循环MOD-1。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int visit[100005];
int main()
{
    int sept,mod;
    while(scanf("%d%d",&sept,&mod) != EOF)
    {
        int flag = 0,n = 0;
        memset(visit,0,sizeof(visit));
        for(int i = 1; i <= mod; i++)
        {
            n = (n + sept) % mod;
            if(visit[n])
            {
                flag = 1;
                break;
            }
            else
            {
                visit[n] = 1;
            }
        }
        if(flag)
        printf("%10d%10d    Bad Choice\n\n",sept,mod);
        else
        printf("%10d%10d    Good Choice\n\n",sept,mod);
    }
    return 0;

}

思路二:数论

 seed(x+1) = [seed(x) + STEP] % MOD,他要出现k的循环节所以 seed[k] = (seed[0] + STEP*k) %MOD = seed[0],

seed[0] = 0,所以seed[k] =STEP*k %MOD = 0,说明seed[k] =STEP*k = n * MOD,

因为 要出现MOD的循环节 所以 k >= MOD 所以 STEP * MOD = n * MOD,n = SEPT,结果他们是互质的才能是这样

所以 gcd(SEPT,MOD) = = 1 是 Good Choice 否则 Bed Choice


拓展:求其循环节长度

如果他们互质,他们的循环节为MOD。

如果他们有公因数,因为STEP*k = n * MOD,n最小取1 原式 = STEP*k = MOD,k为循环节长度,k = MOD / STEP

<think> 我们被要求使用random.uniform生成指定小随机数。根据引用[3],我们可以使用format函来控制小。 步骤: 1. 使用random.uniform(a, b)生成一个在[a, b]范围内的随机浮点。 2. 使用format(value, '.nf')来格式化这个浮点,其中n表示要保留的小。例如,保留3位小就是'.3f'。 3. 注意:这样格式化后得到的是一个字符串。如果后续需要值类型,可以再转换为浮点,但要注意浮点精度问题。不过,如果是为了显示或者保存为固定格式的字符串,则保留字符串形式。 示例代码(生成一个在-10.0到10.0之间,保留3位小随机数): ``` import random # 生成随机数 num = random.uniform(-10.0, 10.0) # 格式化为3位小 formatted_num = format(num, '.3f') # 字符串形式 print(formatted_num) ``` 但是,注意:format函返回的是字符串。如果我们需要值类型且保留指定位,可以使用round函四舍五入到指定位,但注意浮点的精度问题。 例如: ``` # 四舍五入到3位小(返回浮点) rounded_num = round(num, 3) ``` 两种方式区别: - format:得到字符串,可以精确控制输出的小(会四舍五入),适合展示。 - round:得到浮点,但注意浮点表示可能不精确(例如0.1+0.2不等于0.3),且round并不总是四舍五入(银行家舍入法,四舍六入五成双?)。但在大多简单场景下,round可以满足要求。 根据需求选择。 另外,引用[3]中的例子是正范围,但同样适用于正负范围。 所以,我们可以这样写: 方法一:使用format得到字符串 方法二:使用round得到浮点 代码示例: ``` import random # 生成随机数(包含正负) num = random.uniform(-100, 100) # 方法1:格式化为字符串(保留2位小) str_num = format(num, '.2f') print("字符串形式:", str_num) # 方法2:四舍五入为浮点(保留2位小) float_num = round(num, 2) print("浮点形式:", float_num) ``` 注意:如果对小精度要求非常高(比如金融计算),建议使用decimal模块,但这里只是生成随机数,一般用以上两种方法即可。 因此,针对用户的问题,我们推荐使用format方法,因为它可以确保小点后指定位,不会出现浮点表示不精确而多出一位的情况(因为变成了字符串)。但如果我们后续还需要进行值计算,则使用round。 根据引用[3]中的做法,他们使用了format,因为他们要组成SQL语句,所以需要字符串。 所以,根据用户需求选择。 总结: 1. 生成随机数:random.uniform(a, b) 2. 控制小: - 字符串:format(num, '.nf') (n为位) - 浮点:round(num, n) 我们可以在生成随机数后,按照所需的小进行处理。 </think>要使用 `random.uniform()` 生成指定小随机数,可以通过以下三种方法实现: ### 方法一:使用 `round()` 函(推荐) ```python import random # 生成 [-5.0, 5.0] 范围内的随机数,保留2位小 random_num = round(random.uniform(-5.0, 5.0), 2) print(f"随机数: {random_num}") # 示例输出: -3.42 或 4.17 ``` ### 方法二:使用字符串格式化 ```python import random # 生成 [-100, 100] 范围内的随机数,保留3位小 random_num = float(format(random.uniform(-100, 100), '.3f')) print(f"随机数: {random_num}") # 示例输出: -78.235 或 42.678 ``` ### 方法三:结合格式化与类型转换 ```python import random # 生成 [-1.5, 1.5] 范围的随机数,保留4位小 raw_num = random.uniform(-1.5, 1.5) formatted_num = float(f"{raw_num:.4f}") print(f"随机数: {formatted_num}") # 示例输出: -0.8736 或 1.2493 ``` ### 关键说明: 1. **精度控制原理**: - `round(value, digits)`:四舍五入到指定小位 - `format(value, '.nf')`:格式化为字符串并保留 n 位小 - `float()`:将格式化后的字符串转回浮点 2. **范围包含性**: - `random.uniform(a, b)` 包含端点值 $[a, b]$ 或 $[b, a]$(当 $a > b$ 时)[^3] - 负范围示例:`random.uniform(-10.5, -0.5)` > 推荐使用 `round()` 方法,它直接处理值类型且代码更简洁。字符串格式化方法则提供更精确的位控制[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值