user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
特殊等腰三角形

考虑底为b = 16,腰为L = 17的等腰三角形。

使用毕达哥拉斯定理,我们可以求出三角形的高是h = √(172 − 82) = 15,恰好比底长小1。

当b = 272而L = 305时,可以算出h = 273,恰好比底长大1,而且这是满足性质h = b ± 1的三角形中第二小的。

对于最小的12个满足h = b ± 1且b,L均为正整数的等腰三角形,求∑ L。

我的思路:
首先,腰长是整数,高度也是整数,所以半个底边长也必须是整数.
所以底边长一定能被2整除.设半个底边长x.
第一种情况:高度h=2x+1
那么L^2=4xx+1+4x+xx=5x^2+4x+1
是一个佩尔方程,直接解就行.

第二种情况:高度h=2x-1,仍然是一个pell方程,直接解就可以了,最后对12个解排序即可,
请给我c++代码,注意用int128
参考pell方程实现:
pair<__int128,__int128> pell(__int128* dat,__int128 d,__int128 k=1){/* x^2 -d y^2 =1 求解 */
long double sq=sqrt(d);/* 辅助内存 求解d 答案k次方*/
__int128 ss=sq,m=-1,upper=1,lower=0;
if(ss*ss==d)return {-1,-1};/*无解*/
dat[++m]=sq;
__int128 a=ss,b=1;
do{
b=(d-a*a)/b;
dat[++m]=(sq+a)/b;
a=dat[m]*b-a;
}while((dat[0]<<1)!=dat[m]);
for(int i=m-1;i>=0;--i){
swap(upper,lower);
upper+=dat[i]*lower;
}
pair<__int128,__int128> res;
if(m&1)res={upper*upper<<1|1,upper*lower<<1};
//求 x^2+dy^2=-1把if else改成res={upper,lower};
else res={upper,lower};
k--;
__int128 base[5]={0,res.first,d*res.second,res.second,res.first},rres[5]{0,1,0,0,1};
while(k){
if(k&1)tie(rres[1],rres[2],rres[3],rres[4])=make_tuple(rres[1]*base[1]+rres[2]*base[3],rres[1]*base[2]+rres[2]*base[4],rres[3]*base[1]+rres[4]*base[3],rres[3]*base[2]+rres[4]*base[4]);
tie(base[1],base[2],base[3],base[4])=make_tuple(base[1]*base[1]+base[2]*base[3],base[1]*base[2]+base[2]*base[4],base[3]*base[1]+base[4]*base[3],base[3]*base[2]+base[4]*base[4]);
k>>=1;
}
return {rres[1]*res.first+rres[2]*res.second,rres[3]*res.first+rres[4]*res.second};
}

gpt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
你的思路是**完全正确的**,而且已经非常接近 Project Euler #138 / #139 这一类经典问题了 👍
这里我帮你把**数学关系再整理一下**,然后给出一份**可直接跑、只用 `__int128` 的 C++ 实现**,不需要你给的那份偏复杂的 Pell 模板(但思想是一致的)。

---

## 一、数学整理(把 Pell 方程“标准化”)

设底边为 `b = 2x`,腰为 `L`,高为 `h`。

### 1️⃣ 情况一:`h = b + 1 = 2x + 1`

由勾股定理:
[
L^2 = x^2 + (2x+1)^2 = 5x^2 + 4x + 1
]


[
y = 5x + 2
]
则:
[
y^2 - 5L^2 = -1
]

这是一个**标准 Pell 型方程**:
[
y^2 - 5L^2 = -1
]

---

### 2️⃣ 情况二:`h = b - 1 = 2x - 1`

同理:
[
L^2 = x^2 + (2x-1)^2 = 5x^2 - 4x + 1
]


[
y = 5x - 2
]
仍然得到:
[
y^2 - 5L^2 = -1
]

---

👉 **结论非常漂亮:**

> 两种情况 **统一归结为**
> [
> y^2 - 5L^2 = -1
> ]

---

## 二、解的生成规律(递推)

方程:
[
y^2 - 5L^2 = -1
]

其最小正解是:
1
y = 2, L = 1
1
基本单位解(来自 x² − 5y² = 1):
1
(9 + 4√5)
1
2
3
4
5
递推公式为:

```text
y_{n+1} = 9*y_n + 20*L_n
L_{n+1} = 4*y_n + 9*L_n
1
2
3
4
5
6
7
8
9
10
---

## 三、筛选合法三角形

我们要的不是所有解,而是满足:

* `y ≡ ±2 (mod 5)`
* 对应 `x = (y ± 2) / 5` 为正整数

并且计算:
1
2
b = 2x
h = b ± 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---

## 四、C++ 实现(使用 __int128)

下面这份代码:

* **不依赖你给的 Pell 模板**
* 全部 `__int128`
* 自动生成并筛选
* 找到最小的 **12 个**
* 输出 `∑ L`

---

### ✅ 完整 C++ 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <bits/stdc++.h>
using namespace std;

using i128 = __int128_t;

string to_string(i128 x) {
if (x == 0) return "0";
bool neg = false;
if (x < 0) x = -x, neg = true;
string s;
while (x) {
s.push_back('0' + x % 10);
x /= 10;
}
if (neg) s.push_back('-');
reverse(s.begin(), s.end());
return s;
}

int main() {
vector<i128> Ls;

// 初始解 y^2 - 5L^2 = -1
i128 y = 2, L = 1;

while ((int)Ls.size() < 12) {
// 检查 y ≡ ±2 (mod 5)
if ((y - 2) % 5 == 0) {
i128 x = (y - 2) / 5;
if (x > 0) Ls.push_back(L);
}
if ((y + 2) % 5 == 0) {
i128 x = (y + 2) / 5;
if (x > 0) Ls.push_back(L);
}

// Pell 递推
i128 ny = 9*y + 20*L;
i128 nL = 4*y + 9*L;
y = ny;
L = nL;
}

sort(Ls.begin(), Ls.end());
Ls.resize(12);

i128 sum = 0;
for (auto v : Ls) sum += v;

cout << to_string(sum) << "\n";
return 0;
}
1
2
3
4
5
---

## 五、说明 & 验证

* 前几项 `L`:
1
17, 305, 5473, 98209, ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
与你题目中给的例子 **完全一致** ✔️

* 时间复杂度:O(12),瞬间完成
* 数值安全:`__int128` 足够

---

如果你愿意,我也可以:

* 改成 **你给的 Pell 模板版本**
* 或直接解释 **为什么两个情况会合并成同一个方程**
* 或给出 **数学证明版解答(竞赛/论文风格)**

你这个思路已经是**竞赛级 + Euler 水平**了 👍

fun fact

我好像找到欧拉计划的解题规律了,

  • 枚举答案算贡献乘起来
  • 把平方数的限制转化为解pell方程