mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-24 17:05:00 +00:00
184 lines
6.3 KiB
Python
Executable file
184 lines
6.3 KiB
Python
Executable file
"""#
|
||
|
||
### 谜题描述
|
||
In the probability theory the following paradox called Benford's law is known: \"In many lists of random numbers taken from real sources, numbers starting with digit 1 occur much more often than numbers starting with any other digit\" (that's the simplest form of the law).
|
||
|
||
Having read about it on Codeforces, the Hedgehog got intrigued by the statement and wishes to thoroughly explore it. He finds the following similar problem interesting in particular: there are N random variables, the i-th of which can take any integer value from some segment [Li;Ri] (all numbers from this segment are equiprobable). It means that the value of the i-th quantity can be equal to any integer number from a given interval [Li;Ri] with probability 1 / (Ri - Li + 1).
|
||
|
||
The Hedgehog wants to know the probability of the event that the first digits of at least K% of those values will be equal to one. In other words, let us consider some set of fixed values of these random variables and leave only the first digit (the MSD — most significant digit) of each value. Then let's count how many times the digit 1 is encountered and if it is encountered in at least K per cent of those N values, than such set of values will be called a good one. You have to find the probability that a set of values of the given random variables will be a good one.
|
||
|
||
Input
|
||
|
||
The first line contains number N which is the number of random variables (1 ≤ N ≤ 1000). Then follow N lines containing pairs of numbers Li, Ri, each of whom is a description of a random variable. It is guaranteed that 1 ≤ Li ≤ Ri ≤ 1018.
|
||
|
||
The last line contains an integer K (0 ≤ K ≤ 100).
|
||
|
||
All the numbers in the input file are integers.
|
||
|
||
Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).
|
||
|
||
Output
|
||
|
||
Print the required probability. Print the fractional number with such a precision that the relative or absolute error of the result won't exceed 10 - 9.
|
||
|
||
Examples
|
||
|
||
Input
|
||
|
||
1
|
||
1 2
|
||
50
|
||
|
||
|
||
Output
|
||
|
||
0.500000000000000
|
||
|
||
Input
|
||
|
||
2
|
||
1 2
|
||
9 11
|
||
50
|
||
|
||
|
||
Output
|
||
|
||
0.833333333333333
|
||
|
||
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
|
||
```python
|
||
N = input()
|
||
T = [1]+[0]*N
|
||
for i in range(N):
|
||
L,R = map(int,raw_input().split())
|
||
c = 1
|
||
n = 0
|
||
while c<=10**18:
|
||
n += max(0,min(R,2*c-1)-max(L,c)+1)
|
||
c *= 10
|
||
p = float(n)/(R-L+1)
|
||
|
||
B = T
|
||
T = [B[0]*(1-p)]+[0]*N
|
||
for j in range(1,N+1):
|
||
T[j] = B[j]*(1-p)+B[j-1]*p
|
||
|
||
K = input()
|
||
print sum(T[(N*K+99)/100:])
|
||
```
|
||
|
||
|
||
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
|
||
"""
|
||
|
||
from bootcamp import Basebootcamp
|
||
from bootcamp import Basebootcamp
|
||
import math
|
||
import re
|
||
import random
|
||
|
||
class Cfirstdigitlawbootcamp(Basebootcamp):
|
||
def __init__(self, max_N=10, **params):
|
||
super().__init__(**params)
|
||
self.max_N = max_N # 控制问题规模以便测试
|
||
|
||
def case_generator(self):
|
||
N = random.randint(1, self.max_N)
|
||
variables = []
|
||
for _ in range(N):
|
||
# 生成更丰富的数值区间分布
|
||
if random.random() < 0.3:
|
||
# 特殊形式:生成以1开头的大范围数值
|
||
exp = random.randint(0, 17)
|
||
Li = 10**exp
|
||
Ri = 10**exp * 2 - 1
|
||
else:
|
||
# 通用生成逻辑
|
||
exp = random.randint(0, 18)
|
||
Li = random.randint(10**exp // 10, 10**exp - 1) if exp > 0 else 1
|
||
max_exp_ri = random.randint(exp, 18)
|
||
max_ri = min(10**max_exp_ri - 1, 10**18)
|
||
Ri = random.randint(Li, max_ri)
|
||
|
||
variables.append({"L": Li, "R": Ri})
|
||
|
||
K = random.randint(0, 100)
|
||
return {
|
||
"N": N,
|
||
"variables": variables,
|
||
"K": K
|
||
}
|
||
|
||
@staticmethod
|
||
def prompt_func(question_case):
|
||
N = question_case['N']
|
||
variables = question_case['variables']
|
||
K = question_case['K']
|
||
required_num = (N * K + 99) // 100
|
||
|
||
problem = f"""根据本福特定律研究问题,请计算{N}个独立随机变量满足条件的概率:
|
||
|
||
每个变量的取值范围如下:"""
|
||
for idx, var in enumerate(variables, 1):
|
||
problem += f"\n变量{idx}: [{var['L']}, {var['R']}],其中每个整数等概率出现"
|
||
|
||
problem += f"""
|
||
要求计算至少{required_num}个变量的最高位为1的概率(即至少达到{K}%的比例)。
|
||
|
||
请输出精确到小数点后15位的概率值,并确保绝对/相对误差≤1e-9。答案请用[answer]和[/answer]标签包裹。
|
||
|
||
示例:
|
||
[answer]0.123456789012345[/answer]"""
|
||
return problem
|
||
|
||
@staticmethod
|
||
def extract_output(output):
|
||
matches = re.findall(r'\[answer\]([\d.eE+-]+)\s*\[/answer\]', output)
|
||
if not matches:
|
||
return None
|
||
try:
|
||
return float(matches[-1].strip().replace(',', ''))
|
||
except ValueError:
|
||
return None
|
||
|
||
@classmethod
|
||
def _verify_correction(cls, solution, identity):
|
||
try:
|
||
N = identity['N']
|
||
variables = identity['variables']
|
||
K = identity['K']
|
||
|
||
# 动态规划数组初始化
|
||
dp = [1.0] + [0.0] * N
|
||
|
||
for var in variables:
|
||
L, R = var['L'], var['R']
|
||
total = R - L + 1
|
||
|
||
# 计算有效数目
|
||
valid_count = 0
|
||
c = 1
|
||
while c <= 1e18:
|
||
lower_bound = max(L, c)
|
||
upper_bound = min(R, 2 * c - 1)
|
||
valid_count += max(0, upper_bound - lower_bound + 1)
|
||
c *= 10
|
||
|
||
# 更新概率分布
|
||
p = valid_count / total
|
||
new_dp = [0.0] * (N + 1)
|
||
new_dp[0] = dp[0] * (1 - p)
|
||
for j in range(1, N + 1):
|
||
new_dp[j] = dp[j] * (1 - p) + dp[j-1] * p
|
||
dp = new_dp
|
||
|
||
# 计算阈值
|
||
required = (N * K + 99) // 100
|
||
threshold = max(0, min(required, N))
|
||
correct_prob = sum(dp[threshold:]) if threshold <= N else 0.0
|
||
|
||
# 浮点数精确校验
|
||
return math.isclose(solution, correct_prob, rel_tol=1e-9, abs_tol=1e-12)
|
||
except:
|
||
return False
|