mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-30 17:40:42 +00:00
init-commit
This commit is contained in:
commit
18a552597a
3461 changed files with 1150579 additions and 0 deletions
184
internbootcamp/bootcamp/cfirstdigitlaw/cfirstdigitlaw.py
Executable file
184
internbootcamp/bootcamp/cfirstdigitlaw/cfirstdigitlaw.py
Executable file
|
|
@ -0,0 +1,184 @@
|
|||
"""#
|
||||
|
||||
### 谜题描述
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue