init-commit

This commit is contained in:
lilinyang 2025-05-23 15:27:15 +08:00
commit 18a552597a
3461 changed files with 1150579 additions and 0 deletions

View file

@ -0,0 +1,494 @@
"""#
### 谜题描述
Let F_k denote the k-th term of Fibonacci sequence, defined as below:
* F_0 = F_1 = 1
* for any integer n 0, F_{n+2} = F_{n+1} + F_n
You are given a tree with n vertices. Recall that a tree is a connected undirected graph without cycles.
We call a tree a Fib-tree, if its number of vertices equals F_k for some k, and at least one of the following conditions holds:
* The tree consists of only 1 vertex;
* You can divide it into two Fib-trees by removing some edge of the tree.
Determine whether the given tree is a Fib-tree or not.
Input
The first line of the input contains a single integer n (1 n 2 10^5) the number of vertices in the tree.
Then n-1 lines follow, each of which contains two integers u and v (1 u,v n, u v), representing an edge between vertices u and v. It's guaranteed that given edges form a tree.
Output
Print \"YES\" if the given tree is a Fib-tree, or \"NO\" otherwise.
You can print your answer in any case. For example, if the answer is \"YES\", then the output \"Yes\" or \"yeS\" will also be considered as correct answer.
Examples
Input
3
1 2
2 3
Output
YES
Input
5
1 2
1 3
1 4
1 5
Output
NO
Input
5
1 3
1 2
4 5
3 4
Output
YES
Note
In the first sample, we can cut the edge (1, 2), and the tree will be split into 2 trees of sizes 1 and 2 correspondently. Any tree of size 2 is a Fib-tree, as it can be split into 2 trees of size 1.
In the second sample, no matter what edge we cut, the tree will be split into 2 trees of sizes 1 and 4. As 4 isn't F_k for any k, it's not Fib-tree.
In the third sample, here is one possible order of cutting the edges so that all the trees in the process are Fib-trees: (1, 3), (1, 2), (4, 5), (3, 4).
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
```python
#pragma GCC optimize(\"Ofast\")
#pragma GCC target(\"sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma\")
#pragma GCC optimize(\"unroll-loops\")
// #include <atcoder/all>
// #include <bits/stdc++.h>
#include <complex>
#include <queue>
#include <set>
#include <unordered_set>
#include <list>
#include <chrono>
#include <random>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <stack>
#include <iomanip>
#include <fstream>
using namespace std;
// using namespace atcoder;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> p32;
typedef pair<ll, ll> p64;
typedef pair<p64, p64> pp64;
typedef pair<double, double> pdd;
typedef vector<ll> v64;
typedef vector<int> v32;
typedef vector<vector<int>> vv32;
typedef vector<vector<ll>> vv64;
typedef vector<vector<p64>> vvp64;
typedef vector<p64> vp64;
typedef vector<p32> vp32;
ll MOD = 1e9 + 7;
double eps = 1e-12;
#define forn(i, e) for (ll i = 0; i < e; i++)
#define forsn(i, s, e) for (ll i = s; i < e; i++)
#define rforn(i, s) for (ll i = s; i >= 0; i--)
#define rforsn(i, s, e) for (ll i = s; i >= e; i--)
#define ln '\n'
#define dbg(x) cout << #x << \" = \" << x << ln
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define INF 2e18
#define fast_cin() \
ios_base::sync_with_stdio(false); \
cin.tie(NULL); \
cout.tie(NULL)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((ll)(x).size())
#define zero ll(0)
#define set_bits(x) __builtin_popcountll(x)
// #define mint modint998244353
ll mpow(ll a, ll b)
{
if (a == 0)
return 0;
if (b == 0)
return 1;
ll t1 = mpow(a, b / 2);
t1 *= t1;
t1 %= MOD;
if (b % 2)
t1 *= a;
t1 %= MOD;
return t1;
}
ll mpow(ll a, ll b, ll p)
{
if (a == 0)
return 0;
if (b == 0)
return 1;
ll t1 = mpow(a, b / 2, p);
t1 *= t1;
t1 %= p;
if (b % 2)
t1 *= a;
t1 %= p;
return t1;
}
ll modinverse(ll a, ll m)
{
ll m0 = m;
ll y = 0, x = 1;
if (m == 1)
return 0;
while (a > 1)
{
ll q = a / m;
ll t = m;
m = a % m, a = t;
t = y;
y = x - q * y;
x = t;
}
if (x < 0)
x += m0;
return x;
}
mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
ll range(ll l, ll r)
{
return l + mt() % (r - l + 1);
}
ll rev(ll v)
{
return mpow(v, MOD - 2);
}
int LIM = 2e5 + 100;
vv64 adj(LIM);
v64 fib(1000, 1);
v64 S(LIM, 0);
vp64 edges(1);
v64 active(1);
int N;
int node;
void dfs(int n, int pa, int &idx, int k)
{
S[n] = 1;
for (int c : adj[n])
{
if (active[c] == 0)
continue;
p64 temp = edges[c];
int v;
if (temp.fi == n)
v = temp.se;
else
v = temp.fi;
if (v == pa)
continue;
dfs(v, n, idx, k);
if (S[v] == fib[k - 1] || S[v] == fib[k - 2])
{
idx = c;
node = v;
}
S[n] += S[v];
}
}
bool check(int n, int k)
{
if (k <= 2)
return true;
int idx = -1;
dfs(n, -1, idx, k);
// cout << \"a\" << endl;
if (idx == -1)
return false;
active[idx] = 0;
int u = edges[idx].fi, v = edges[idx].se;
if (u == node)
swap(u, v);
// cout << n << \" \" << u << \" \" << v << endl;
int k1, k2;
k1 = k - 1;
k2 = k - 2;
if (S[v] == fib[k - 1])
swap(k1, k2);
bool f1 = check(u, k1), f2 = check(v, k2);
return f1 && f2;
}
void solve()
{
ll n;
cin >> n;
N = n;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
edges.push_back({u, v});
active.push_back(1);
adj[u].push_back(i);
adj[v].push_back(i);
}
int k = -1;
for (int i = 1; i < 1000; i++)
{
if (fib[i] == n)
{
k = i;
break;
}
}
if (k == -1)
{
cout << \"NO\" << endl;
return;
}
if (check(1, k))
{
cout << \"YES\" << endl;
}
else
{
cout << \"NO\" << endl;
}
}
int main()
{
fast_cin();
ll t = 1;
for (int i = 2; i < 50; i++)
{
fib[i] = fib[i - 1] + fib[i - 2];
}
// cin >> t;
forn(i, t)
{
// cout << \"Case #\" << i+1 << \": \";
solve();
}
return 0;
}
```
请完成上述谜题的训练场环境类实现包括所有必要的方法
"""
from bootcamp import Basebootcamp
import re
import random
from bootcamp import Basebootcamp
class Efibtreebootcamp(Basebootcamp):
def __init__(self, yes_prob=0.5, case_type=None, max_n=200000):
super().__init__()
self.yes_prob = yes_prob
self.case_type = case_type
self.max_n = max_n
# 预计算斐波那契数列
self.fib = [1, 1]
while True:
next_f = self.fib[-1] + self.fib[-2]
if next_f > max_n:
break
self.fib.append(next_f)
self.fib_set = set(self.fib)
def _build_fib_tree(self, k):
"""动态构建符合Fib-tree的随机结构"""
if k == 0 or k == 1:
return {'nodes': [1], 'edges': []}
# 随机选择分割比例(允许不同分割方向)
left_k = k-1
right_k = k-2
if random.random() < 0.5 and k >= 3:
left_k, right_k = right_k, left_k
left = self._build_fib_tree(left_k)
right = self._build_fib_tree(right_k)
# 动态计算节点偏移
max_left = max(left['nodes'])
right_nodes = [n + max_left for n in right['nodes']]
right_edges = [[u+max_left, v+max_left] for u, v in right['edges']]
# 随机选择连接点
connect_point = random.choice(left['nodes'])
new_node = max_left + 1 if not right['nodes'] else right_nodes[0]
return {
'nodes': left['nodes'] + right_nodes,
'edges': left['edges'] + right_edges + [[connect_point, new_node]]
}
def case_generator(self):
# 类型决策逻辑
if self.case_type is not None:
generate_yes = (self.case_type == 'YES')
else:
generate_yes = random.random() < self.yes_prob
if generate_yes:
valid_ks = [k for k, f in enumerate(self.fib) if 1 <= f <= self.max_n and k >= 0]
if not valid_ks:
valid_ks = [0, 1]
k = random.choice(valid_ks)
n = self.fib[k]
# 特殊处理小案例
if k <= 1:
return {'n': n, 'edges': [], 'expected': 'YES'}
tree = self._build_fib_tree(k)
return {
'n': n,
'edges': tree['edges'],
'expected': 'YES'
}
else:
# 生成两种NO案例类型
if random.random() < 0.5:
# 类型An非斐波那契数
while True:
n = random.randint(1, self.max_n)
if n not in self.fib_set:
break
# 生成链式结构
edges = [[i, i+1] for i in range(1, n)]
return {'n': n, 'edges': edges, 'expected': 'NO'}
else:
# 类型B斐波那契数但结构非法
valid_ks = [k for k, f in enumerate(self.fib) if f >=5 and f <= self.max_n]
k = random.choice(valid_ks)
n = self.fib[k]
# 生成星型结构
edges = [[1, i] for i in range(2, n+1)]
return {'n': n, 'edges': edges, 'expected': 'NO'}
@staticmethod
def prompt_func(question_case):
n = question_case['n']
edges = question_case['edges']
edge_list = '\n'.join(f"{u} {v}" for u, v in edges)
return f"""判断给定的树是否为Fib-tree。规则如下
1. 顶点数必须是斐波那契数F_0=1, F_1=1, F_n=F_{{n-1}}+F_{{n-2}}
2. 单个顶点或可通过移除一条边分割为两个Fib-tree
输入
{n}
{edge_list}
请将答案YES/NO放在[answer]标签内例如[answer]YES[/answer]"""
@staticmethod
def extract_output(output):
matches = re.findall(r'\[answer\](.*?)\[/answer\]', output, re.IGNORECASE)
if not matches:
return None
answer = matches[-1].strip().upper()
return answer if answer in {'YES', 'NO'} else None
@classmethod
def _verify_correction(cls, solution, identity):
n = identity['n']
edges = identity['edges']
# 快速判断标记案例
if 'expected' in identity:
return solution == identity['expected']
# 构建邻接表
adj = [[] for _ in range(n+1)]
for u, v in edges:
adj[u].append(v)
adj[v].append(u)
# 预计算斐波那契序列
fib = [1, 1]
while fib[-1] < n:
fib.append(fib[-1] + fib[-2])
if n not in fib:
return solution == 'NO'
k = fib.index(n)
# 改进的递归验证算法
def validate(root, parent):
size = 1
valid_splits = []
for child in adj[root]:
if child == parent:
continue
child_size = validate(child, root)
if child_size == -1:
return -1
size += child_size
valid_splits.append(child_size)
# 基准情况
if size == 1:
return 1
# 检查当前子树是否可分割
required = [fib[k-1], fib[k-2]]
for s in valid_splits:
if s in required:
remaining = size - 1 - s # 减去当前根节点
if remaining in required:
return size
return -1
return (solution == 'YES') == (validate(1, -1) != -1)