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
230
internbootcamp/bootcamp/btreearray/btreearray.py
Executable file
230
internbootcamp/bootcamp/btreearray/btreearray.py
Executable file
|
|
@ -0,0 +1,230 @@
|
|||
"""#
|
||||
|
||||
### 谜题描述
|
||||
You are given a tree consisting of n nodes. You generate an array from the tree by marking nodes one by one.
|
||||
|
||||
Initially, when no nodes are marked, a node is equiprobably chosen and marked from the entire tree.
|
||||
|
||||
After that, until all nodes are marked, a node is equiprobably chosen and marked from the set of unmarked nodes with at least one edge to a marked node.
|
||||
|
||||
It can be shown that the process marks all nodes in the tree.
|
||||
|
||||
The final array a is the list of the nodes' labels in order of the time each node was marked.
|
||||
|
||||
Find the expected number of inversions in the array that is generated by the tree and the aforementioned process.
|
||||
|
||||
The number of inversions in an array a is the number of pairs of indices (i, j) such that i < j and a_i > a_j. For example, the array [4, 1, 3, 2] contains 4 inversions: (1, 2), (1, 3), (1, 4), (3, 4).
|
||||
|
||||
Input
|
||||
|
||||
The first line contains a single integer n (2 ≤ n ≤ 200) — the number of nodes in the tree.
|
||||
|
||||
The next n - 1 lines each contains two integers x and y (1 ≤ x, y ≤ n; x ≠ y), denoting an edge between node x and y.
|
||||
|
||||
It's guaranteed that the given edges form a tree.
|
||||
|
||||
Output
|
||||
|
||||
Output the expected number of inversions in the generated array modulo 10^9+7.
|
||||
|
||||
Formally, let M = 10^9+7. It can be shown that the answer can be expressed as an irreducible fraction p/q, where p and q are integers and q not ≡ 0 \pmod{M}. Output the integer equal to p ⋅ q^{-1} mod M. In other words, output such an integer x that 0 ≤ x < M and x ⋅ q ≡ p \pmod{M}.
|
||||
|
||||
Examples
|
||||
|
||||
Input
|
||||
|
||||
|
||||
3
|
||||
1 2
|
||||
1 3
|
||||
|
||||
|
||||
Output
|
||||
|
||||
|
||||
166666669
|
||||
|
||||
|
||||
Input
|
||||
|
||||
|
||||
6
|
||||
2 1
|
||||
2 3
|
||||
6 1
|
||||
1 4
|
||||
2 5
|
||||
|
||||
|
||||
Output
|
||||
|
||||
|
||||
500000009
|
||||
|
||||
|
||||
Input
|
||||
|
||||
|
||||
5
|
||||
1 2
|
||||
1 3
|
||||
1 4
|
||||
2 5
|
||||
|
||||
|
||||
Output
|
||||
|
||||
|
||||
500000007
|
||||
|
||||
Note
|
||||
|
||||
This is the tree from the first sample:
|
||||
|
||||
<image>
|
||||
|
||||
For the first sample, the arrays are almost fixed. If node 2 is chosen initially, then the only possible array is [2, 1, 3] (1 inversion). If node 3 is chosen initially, then the only possible array is [3, 1, 2] (2 inversions). If node 1 is chosen initially, the arrays [1, 2, 3] (0 inversions) and [1, 3, 2] (1 inversion) are the only possibilities and equiprobable. In total, the expected number of inversions is 1/3⋅ 1 + 1/3 ⋅ 2 + 1/3 ⋅ (1/2 ⋅ 0 + 1/2 ⋅ 1) = 7/6.
|
||||
|
||||
166666669 ⋅ 6 = 7 \pmod {10^9 + 7}, so the answer is 166666669.
|
||||
|
||||
This is the tree from the second sample:
|
||||
|
||||
<image>
|
||||
|
||||
This is the tree from the third sample:
|
||||
|
||||
<image>
|
||||
|
||||
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
|
||||
```python
|
||||
m=10**9+7
|
||||
n=input()
|
||||
R=range(n)
|
||||
d=[n*[m]for _ in R]
|
||||
for _ in R[1:]:a,b=map(int,raw_input().split());a-=1;b-=1;d[a][b]=d[b][a]=1;d[a][a]=d[b][b]=s=0
|
||||
for k in R:
|
||||
for i in R:
|
||||
for j in R:d[i][j]=min(d[i][j],d[i][k]+d[k][j])
|
||||
c=[[1]+n*[0]for _ in[0]+R]
|
||||
for i in R:
|
||||
for j in R:c[i+1][j+1]=(c[i][j+1]+c[i+1][j])*-~m/2%m
|
||||
for i in R:
|
||||
for j in R[i+1:]:
|
||||
for k in R:x,y=d[i][k],d[j][k];v=(x+y-d[i][j])/2;s+=c[x-v][y-v]
|
||||
print s*pow(n,m-2,m)%m
|
||||
```
|
||||
|
||||
|
||||
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
|
||||
"""
|
||||
|
||||
from bootcamp import Basebootcamp
|
||||
import random
|
||||
import re
|
||||
from bootcamp import Basebootcamp
|
||||
|
||||
MOD = 10**9 + 7
|
||||
|
||||
def generate_random_tree(n):
|
||||
if n == 1:
|
||||
return []
|
||||
nodes = list(range(1, n + 1))
|
||||
edges = []
|
||||
connected = {nodes[0]}
|
||||
unconnected = set(nodes[1:])
|
||||
while unconnected:
|
||||
u = random.choice(list(connected))
|
||||
v = random.choice(list(unconnected))
|
||||
edges.append((u, v))
|
||||
connected.add(v)
|
||||
unconnected.remove(v)
|
||||
return edges
|
||||
|
||||
def calculate_expected_inversion(n, edges):
|
||||
edges_zero = [(a-1, b-1) for a, b in edges]
|
||||
d = [[MOD] * n for _ in range(n)]
|
||||
for i in range(n):
|
||||
d[i][i] = 0
|
||||
for a, b in edges_zero:
|
||||
d[a][b] = 1
|
||||
d[b][a] = 1
|
||||
for k in range(n):
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
d[i][j] = min(d[i][j], d[i][k] + d[k][j])
|
||||
c = [[1] + [0] * n for _ in range(n + 1)]
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
term = (c[i][j+1] + c[i+1][j]) % MOD
|
||||
term = term * ((MOD + 1) // 2) % MOD
|
||||
c[i+1][j+1] = term
|
||||
s = 0
|
||||
for i in range(n):
|
||||
for j in range(i + 1, n):
|
||||
for k in range(n):
|
||||
x = d[i][k]
|
||||
y = d[j][k]
|
||||
v = (x + y - d[i][j]) // 2
|
||||
dxv = x - v
|
||||
dyv = y - v
|
||||
if dxv >= 0 and dyv >= 0 and dxv < len(c) and dyv < len(c[dxv]):
|
||||
term = c[dxv][dyv]
|
||||
else:
|
||||
term = 0
|
||||
s = (s + term) % MOD
|
||||
inv_n = pow(n, MOD-2, MOD)
|
||||
result = (s * inv_n) % MOD
|
||||
return result
|
||||
|
||||
class Btreearraybootcamp(Basebootcamp):
|
||||
def __init__(self, min_nodes=2, max_nodes=200):
|
||||
self.min_nodes = min_nodes
|
||||
self.max_nodes = max_nodes
|
||||
|
||||
def case_generator(self):
|
||||
n = random.randint(self.min_nodes, self.max_nodes)
|
||||
edges = generate_random_tree(n)
|
||||
correct_answer = calculate_expected_inversion(n, edges)
|
||||
return {
|
||||
'n': n,
|
||||
'edges': edges,
|
||||
'correct_answer': correct_answer
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def prompt_func(question_case):
|
||||
edges_str = '\n'.join(f"{a} {b}" for a, b in question_case['edges'])
|
||||
prompt = f"""You are given a tree consisting of {question_case['n']} nodes. Calculate the expected number of inversions in the array generated by the marking process, modulo 1,000,000,007.
|
||||
|
||||
Input Format:
|
||||
- First line: {question_case['n']}
|
||||
- Next {question_case['n']-1} lines: Each line contains two integers representing an edge.
|
||||
|
||||
Input for this problem:
|
||||
{question_case['n']}
|
||||
{edges_str}
|
||||
|
||||
Process Rules:
|
||||
1. Initially, a node is chosen uniformly at random and marked.
|
||||
2. Until all nodes are marked, an unmarked node adjacent to a marked node is chosen uniformly at random and marked.
|
||||
3. The array is the order of marking.
|
||||
|
||||
Output the expected number of inversions modulo 1,000,000,007 as p * q⁻¹ mod MOD, where the expectation is p/q.
|
||||
|
||||
Put your answer within [answer] tags, like [answer]123456789[/answer]."""
|
||||
return prompt
|
||||
|
||||
@staticmethod
|
||||
def extract_output(output):
|
||||
matches = re.findall(r'\[answer\](.*?)\[/answer\]', output, re.DOTALL)
|
||||
if not matches:
|
||||
return None
|
||||
last_match = matches[-1].strip()
|
||||
try:
|
||||
return int(last_match)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _verify_correction(cls, solution, identity):
|
||||
return solution == identity.get('correct_answer')
|
||||
Loading…
Add table
Add a link
Reference in a new issue