We are given an integer-sided triangle \(ABC\) with
$$BC \le AC \le AB.$$
The angle bisector of \(\angle ACB\) meets the line through \(B\) parallel to the tangent at \(C\) to the circumcircle at a point \(E\). We must count all triangles with perimeter at most \(100000\) for which the segment \(BE\) has integer length.
The program uses
$$a=BC,\qquad b=CA,\qquad c=AB,$$
so the ordering condition becomes
$$a\le b\le c.$$
The triangle inequalities and perimeter bound then force
$$c < a+b,\qquad a+b+c\le N.$$
Let the angles of triangle \(ABC\) be \(A,B,C\) at the corresponding vertices. Because \(CE\) is the angle bisector of \(\angle C\), we have
$$\angle ECB=\frac{C}{2}.$$
The line through \(B\) is parallel to the tangent at \(C\) to the circumcircle. By the tangent-chord theorem, the angle between that tangent and the chord \(CB\) equals the angle at \(A\). Therefore, in triangle \(CBE\),
$$\angle CBE = A.$$
Now apply the sine rule in triangle \(CBE\):
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
So
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
To simplify the denominator, use \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
hence
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
On the other hand, by the sine rule in triangle \(ABC\),
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
so
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
and
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
Dividing these gives
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
Substituting into the previous expression yields the key identity
$$BE=\frac{ac}{a+b}.$$
The problem asks when \(BE\) is an integer. Because \(a,b,c\) are integers, the identity above shows that this is equivalent to
$$a+b \mid ac.$$
This is the decisive reduction: the geometric condition disappears completely and the rest of the problem becomes arithmetic counting.
Fix \(a\) and \(b\). Since \(b\le c\) and the triangle inequality requires \(c<a+b\), while the perimeter bound requires \(c\le N-a-b\), the allowed interval is
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
If \(c_{\max}<b\), then no triangle exists for that pair \((a,b)\).
Let
$$s=a+b,\qquad g=\gcd(a,b).$$
Because
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
we may write
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
The divisibility condition
$$s\mid ac$$
becomes
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
Since \(a_1\) and \(s_1\) are coprime, this is equivalent to
$$s_1 \mid c,$$
that is,
$$\frac{s}{g}\mid c.$$
So for fixed \((a,b)\), the valid values of \(c\) form an arithmetic progression with step
$$d=\frac{a+b}{\gcd(a,b)}.$$
We now only need to count multiples of \(d\) inside the interval \([b,c_{\max}]\). The answer is
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
This replaces a full inner scan over all \(c\) values by a constant-time formula.
The code validates two different parts of the reasoning.
Geometric checkpoint. For sample triangles such as \((3,4,5)\), \((5,5,8)\), \((7,8,9)\), the function be_from_geometry computes \(BE\) directly from coordinates and checks that it matches
$$\frac{ac}{a+b}.$$
Counting checkpoint. For small perimeter limits \(150,300,600\), the fast arithmetic count is compared with a brute-force loop over every admissible \(c\). This confirms that the divisibility reformulation is exact.
count_range loops over ordered side pairs \((a,b)\), computes \(c_{\max}\), the gcd \(g\), the step \(d=(a+b)/g\), and adds the floor-difference count of multiples of \(d\) in the allowed interval. solve_fast parallelizes only over disjoint ranges of \(a\); mathematically each \((a,b)\) contributes independently. solve_bruteforce is kept only for checkpoint verification.
The outer loops run only over \(a\) and \(b\). Each pair contributes constant-time arithmetic, so the running time is roughly
$$O(N^2),$$
which is a major improvement over the cubic brute-force scan over all \((a,b,c)\). Memory usage is \(O(1)\) apart from thread-local counters.
Gegeben ist ein ganzzahliges Dreieck \(ABC\) mit
$$BC \le AC \le AB.$$
Die Winkelhalbierende von \(\angle ACB\) schneidet die durch \(B\) verlaufende Gerade, die zur Tangente im Punkt \(C\) an den Umkreis parallel ist, im Punkt \(E\). Gesucht ist die Anzahl aller Dreiecke mit Umfang höchstens \(100000\), für die die Strecke \(BE\) ganzzahlig ist.
Im Programm gilt
$$a=BC,\qquad b=CA,\qquad c=AB,$$
also wird die Ordnungsbedingung zu
$$a\le b\le c.$$
Dazu kommen die Dreiecksungleichung und die Umfangsschranke:
$$c < a+b,\qquad a+b+c\le N.$$
Bezeichne die Innenwinkel von \(ABC\) mit \(A,B,C\). Weil \(CE\) die Winkelhalbierende von \(\angle C\) ist, gilt
$$\angle ECB=\frac{C}{2}.$$
Die durch \(B\) gehende Gerade ist parallel zur Tangente im Punkt \(C\) an den Umkreis. Nach dem Tangenten-Sehnen-Satz ist der Winkel zwischen Tangente und Sehne \(CB\) gleich dem Winkel bei \(A\). Daher ist im Dreieck \(CBE\)
$$\angle CBE = A.$$
Mit dem Sinussatz in \(CBE\) folgt
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
Also
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
Nun benutze \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
also
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
Andererseits liefert der Sinussatz im ursprünglichen Dreieck
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
und damit
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
sowie
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
Daraus folgt
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
Einsetzen liefert die Schlüsselformel
$$BE=\frac{ac}{a+b}.$$
Gesucht ist, wann \(BE\) ganzzahlig ist. Weil \(a,b,c\) ganzzahlig sind, ist das nach der obigen Identität genau äquivalent zu
$$a+b \mid ac.$$
Damit verschwindet die Geometrie vollständig; der Rest ist nur noch ein zahlentheoretisches Zählproblem.
Fixiere \(a\) und \(b\). Aus \(b\le c\), der Bedingung \(c<a+b\) und der Umfangsschranke folgt
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
Falls \(c_{\max}<b\), existiert für dieses Paar \((a,b)\) kein Dreieck.
Setze
$$s=a+b,\qquad g=\gcd(a,b).$$
Wegen
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g$$
schreiben wir
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
Dann wird
$$s\mid ac$$
zu
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
Da \(a_1\) und \(s_1\) teilerfremd sind, ist dies gleichbedeutend mit
$$s_1 \mid c,$$
also
$$\frac{s}{g}\mid c.$$
Für feste \((a,b)\) liegen die gültigen \(c\)-Werte also in einer arithmetischen Folge mit Schrittweite
$$d=\frac{a+b}{\gcd(a,b)}.$$
Nun müssen nur noch Vielfache von \(d\) im Intervall \([b,c_{\max}]\) gezählt werden. Ihre Anzahl ist
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
Damit wird ein vollständiger innerer Lauf über alle \(c\) durch eine \(O(1)\)-Formel ersetzt.
Der Code validiert zwei verschiedene Teile des Arguments.
Geometrische Prüfung. Für Testdreiecke wie \((3,4,5)\), \((5,5,8)\), \((7,8,9)\) berechnet be_from_geometry die Strecke \(BE\) direkt aus Koordinaten und vergleicht mit
$$\frac{ac}{a+b}.$$
Zählprüfung. Für kleine Umfangsgrenzen \(150,300,600\) wird die schnelle arithmetische Zählung mit einem Brute-Force-Durchlauf über alle zulässigen \(c\) verglichen. Das bestätigt, dass die Teilbarkeitsreduktion exakt ist.
count_range durchläuft alle geordneten Seitenpaare \((a,b)\), berechnet \(c_{\max}\), den ggT \(g\), die Schrittweite \(d=(a+b)/g\) und addiert die Floor-Differenz für die Vielfachen von \(d\) im zulässigen Intervall. solve_fast parallelisiert nur über disjunkte \(a\)-Bereiche; mathematisch trägt jedes Paar \((a,b)\) unabhängig zum Ergebnis bei. solve_bruteforce bleibt nur für Kontrolltests erhalten.
Die äußeren Schleifen laufen nur über \(a\) und \(b\). Pro Paar entsteht konstante arithmetische Arbeit, daher ist die Laufzeit näherungsweise
$$O(N^2),$$
also deutlich besser als der kubische Brute-Force-Scan über alle \((a,b,c)\). Der Speicherverbrauch ist \(O(1)\) abgesehen von thread-lokalen Zählern.
Elimizde
$$BC \le AC \le AB$$
şartını sağlayan tam kenarlı bir \(ABC\) üçgeni var. \(\angle ACB\)'nin açıortayı ile, \(C\) noktasında çevrel çembere çizilen teğete paralel ve \(B\)'den geçen doğrunun kesişim noktası \(E\) olsun. İstenen, çevresi \(100000\)'i aşmayan ve \(BE\) uzunluğu tam sayı olan bütün üçgenlerin sayısıdır.
Program şu isimlendirmeyi kullanır:
$$a=BC,\qquad b=CA,\qquad c=AB.$$
Dolayısıyla sıralama koşulu
$$a\le b\le c$$
haline gelir. Üçgen eşitsizliği ve çevre sınırı da
$$c < a+b,\qquad a+b+c\le N$$
koşullarını verir.
Üçgen \(ABC\)'nin açılarını karşılık gelen köşelerde \(A,B,C\) ile gösterelim. \(CE\), \(\angle C\)'nin açıortayı olduğundan
$$\angle ECB=\frac{C}{2}$$
olur. \(B\)'den geçen doğru, \(C\)'de çevrel çembere çizilen teğete paraleldir. Teğet-kiriş teoremine göre, bu teğet ile \(CB\) kirişi arasındaki açı, \(A\) köşesindeki açıya eşittir. Dolayısıyla \(CBE\) üçgeninde
$$\angle CBE = A$$
vardır. Şimdi \(CBE\) üçgenine sinüs teoremini uygularız:
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
Buradan
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}$$
çıkar. Şimdi \(A+B+C=\pi\) kullanılır:
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
yani
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
Öte yandan asıl üçgende sinüs teoremi
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C$$
verir. Buradan
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right)$$
ve
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right)$$
elde edilir. Dolayısıyla
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
Bunu yukarıdaki ifadeye yerleştirince temel kimlik gelir:
$$BE=\frac{ac}{a+b}.$$
Problem \(BE\)'nin tam sayı olmasını soruyor. \(a,b,c\) zaten tam sayı olduğundan, yukarıdaki formül bunun tam olarak şu koşula eşdeğer olduğunu gösterir:
$$a+b \mid ac.$$
Böylece geometrik koşul tamamen kaybolur; geriye yalnızca aritmetik bir sayım problemi kalır.
\(a\) ve \(b\)'yi sabitleyelim. \(b\le c\), \(c<a+b\) ve çevre sınırı birlikte
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b)$$
aralığını verir. Eğer \(c_{\max}<b\) ise bu \((a,b)\) çifti için hiç üçgen yoktur.
Şunları tanımlayalım:
$$s=a+b,\qquad g=\gcd(a,b).$$
Çünkü
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
şöyle yazabiliriz:
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
Şimdi
$$s\mid ac$$
koşulu
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c$$
şeklinde yazılır. \(a_1\) ile \(s_1\) aralarında asal olduğundan bu,
$$s_1 \mid c$$
ile eşdeğerdir; yani
$$\frac{s}{g}\mid c.$$
Demek ki sabit \((a,b)\) için geçerli \(c\) değerleri, adımı
$$d=\frac{a+b}{\gcd(a,b)}$$
olan bir aritmetik dizidir.
Artık yapılacak tek şey, \([b,c_{\max}]\) aralığındaki \(d\) katlarını saymaktır. Sayı tam olarak
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor$$
olur. Böylece bütün \(c\)'leri tek tek tarayan iç döngü yerine sabit zamanlı bir formül elde edilir.
Kod argümanın iki farklı kısmını doğrular.
Geometrik kontrol. \((3,4,5)\), \((5,5,8)\), \((7,8,9)\) gibi örnek üçgenler için be_from_geometry koordinatlarla \(BE\)'yi doğrudan hesaplar ve bunun
$$\frac{ac}{a+b}$$
ile aynı çıktığını sınar.
Sayım kontrolü. Küçük çevre sınırları \(150,300,600\) için hızlı aritmetik sayım, bütün uygun \(c\) değerlerini brute-force deneyen sürümle karşılaştırılır. Bu da bölünebilirlik indirgemesinin tam olduğunu gösterir.
count_range, sıralı \((a,b)\) çiftlerini dolaşır; \(c_{\max}\), \(g\), \(d=(a+b)/g\) hesaplanır ve uygun aralıktaki \(d\) katlarının sayısı floor farkı ile eklenir. solve_fast sadece farklı \(a\) aralıklarını paralelleştirir; matematiksel olarak her \((a,b)\) çifti bağımsız katkı verir. solve_bruteforce yalnızca checkpoint doğrulaması için tutulmuştur.
Dış döngüler yalnızca \(a\) ve \(b\) üzerinde çalışır. Her çift sabit sayıda aritmetik işlem üretir; dolayısıyla toplam süre yaklaşık
$$O(N^2)$$
olur. Bu, bütün \((a,b,c)\) üçlülerini tarayan kaba kuvvet \(O(N^3)\) yaklaşımına göre ciddi bir iyileşmedir. Bellek kullanımı thread-local sayaçlar dışında \(O(1)\)'dir.
Se da un triángulo entero \(ABC\) con
$$BC \le AC \le AB.$$
La bisectriz del ángulo \(\angle ACB\) corta a la recta por \(B\) paralela a la tangente en \(C\) a la circunferencia circunscrita en un punto \(E\). Debemos contar todos los triángulos de perímetro a lo sumo \(100000\) para los cuales \(BE\) es entero.
El programa usa
$$a=BC,\qquad b=CA,\qquad c=AB,$$
de modo que la condición de orden es
$$a\le b\le c.$$
La desigualdad triangular y el límite de perímetro imponen
$$c < a+b,\qquad a+b+c\le N.$$
Sea \(A,B,C\) la notación usual de los ángulos. Como \(CE\) es la bisectriz de \(\angle C\), tenemos
$$\angle ECB=\frac{C}{2}.$$
La recta por \(B\) es paralela a la tangente en \(C\) a la circunferencia circunscrita. Por el teorema tangente-cuerda, el ángulo entre esa tangente y la cuerda \(CB\) es igual al ángulo en \(A\). Por tanto, en el triángulo \(CBE\),
$$\angle CBE = A.$$
Aplicando la ley de los senos en \(CBE\):
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
Así,
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
Ahora usamos \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
y por tanto
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
Además, por la ley de los senos en \(ABC\),
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
de donde
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
y
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
Dividiendo, obtenemos
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
Sustituyendo, aparece la identidad clave
$$BE=\frac{ac}{a+b}.$$
El problema pregunta cuándo \(BE\) es entero. Como \(a,b,c\) ya son enteros, la identidad anterior muestra que esto equivale exactamente a
$$a+b \mid ac.$$
Ésta es la reducción decisiva: la condición geométrica desaparece y el resto del problema pasa a ser un conteo aritmético.
Fijamos \(a\) y \(b\). Como \(b\le c\), la desigualdad triangular exige \(c<a+b\), y el límite de perímetro exige \(c\le N-a-b\). Por tanto, el intervalo permitido es
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
Si \(c_{\max}<b\), no existe triángulo para ese par \((a,b)\).
Sea
$$s=a+b,\qquad g=\gcd(a,b).$$
Como
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
podemos escribir
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
Entonces la condición
$$s\mid ac$$
se transforma en
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
Como \(a_1\) y \(s_1\) son coprimos, esto equivale a
$$s_1 \mid c,$$
es decir,
$$\frac{s}{g}\mid c.$$
Así, para \((a,b)\) fijo, los \(c\) válidos forman una progresión aritmética con paso
$$d=\frac{a+b}{\gcd(a,b)}.$$
Solo queda contar los múltiplos de \(d\) dentro de \([b,c_{\max}]\). Su número es
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
Eso sustituye el barrido lineal sobre todos los \(c\) por una fórmula de tiempo constante.
El código valida dos partes distintas del razonamiento.
Control geométrico. Para triángulos de prueba como \((3,4,5)\), \((5,5,8)\), \((7,8,9)\), la función be_from_geometry calcula \(BE\) directamente con coordenadas y comprueba que coincide con
$$\frac{ac}{a+b}.$$
Control de conteo. Para límites pequeños \(150,300,600\), el conteo aritmético rápido se compara con un barrido bruto sobre todos los \(c\) admisibles. Eso confirma que la reformulación divisoria es exacta.
count_range recorre los pares ordenados \((a,b)\), calcula \(c_{\max}\), el gcd \(g\), el paso \(d=(a+b)/g\), y suma la diferencia de pisos que cuenta los múltiplos de \(d\) en el intervalo permitido. solve_fast solo paraleliza rangos disjuntos de \(a\); matemáticamente cada par \((a,b)\) contribuye de forma independiente. solve_bruteforce se conserva solo para los checkpoints.
Los bucles exteriores recorren solo \(a\) y \(b\). Cada par aporta aritmética de tiempo constante, así que el coste total es aproximadamente
$$O(N^2),$$
muy por debajo del enfoque bruto cúbico sobre todos los \((a,b,c)\). La memoria es \(O(1)\), aparte de contadores locales por hilo.
给定一个整数边三角形 \(ABC\),满足
$$BC \le AC \le AB.$$
\(\angle ACB\) 的角平分线与“过 \(B\) 且平行于外接圆在 \(C\) 点切线”的直线交于 \(E\)。我们要统计所有周长不超过 \(100000\)、并且 \(BE\) 为整数的三角形个数。
程序中采用
$$a=BC,\qquad b=CA,\qquad c=AB,$$
因此大小顺序变成
$$a\le b\le c.$$
三角形不等式与周长限制则给出
$$c < a+b,\qquad a+b+c\le N.$$
把三角形 \(ABC\) 的三个角仍记为 \(A,B,C\)。因为 \(CE\) 是 \(\angle C\) 的角平分线,所以
$$\angle ECB=\frac{C}{2}.$$
过 \(B\) 的那条直线与外接圆在 \(C\) 点的切线平行。由切线-弦定理可知,切线与弦 \(CB\) 的夹角等于顶点 \(A\) 处的圆周角。因此在三角形 \(CBE\) 中有
$$\angle CBE = A.$$
对三角形 \(CBE\) 使用正弦定理:
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
于是
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
再利用 \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
所以
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
另一方面,在原三角形中由正弦定理有
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
因此
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
以及
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
两式相除得到
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
代回去便得到核心恒等式
$$BE=\frac{ac}{a+b}.$$
题目要求 \(BE\) 是整数。由于 \(a,b,c\) 本来就是整数,上面的恒等式说明这与
$$a+b \mid ac$$
完全等价。到这里,几何条件就彻底消失了,问题变成纯粹的算术计数。
固定 \(a,b\)。因为 \(b\le c\),三角形不等式要求 \(c<a+b\),而周长上界要求 \(c\le N-a-b\)。所以允许区间是
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
若 \(c_{\max}<b\),则该 \((a,b)\) 下根本不存在三角形。
设
$$s=a+b,\qquad g=\gcd(a,b).$$
因为
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
可写成
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
于是条件
$$s\mid ac$$
就化为
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
由于 \(a_1\) 与 \(s_1\) 互素,这进一步等价于
$$s_1 \mid c,$$
也就是
$$\frac{s}{g}\mid c.$$
因此,对固定的 \((a,b)\),所有合法 \(c\) 组成一个公差为
$$d=\frac{a+b}{\gcd(a,b)}$$
的等差数列。
现在只需统计区间 \([b,c_{\max}]\) 内有多少个 \(d\) 的倍数。答案是
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
这样就把原本逐个检查 \(c\) 的内层线性扫描,替换成了常数时间公式。
代码验证了推导中的两个不同层面。
几何校验。 对 \((3,4,5)\)、\((5,5,8)\)、\((7,8,9)\) 等样例三角形,函数 be_from_geometry 直接用坐标算出 \(BE\),并检查它是否等于
$$\frac{ac}{a+b}.$$
计数校验。 对较小的周长上界 \(150,300,600\),快速算术计数会与真正逐个枚举所有可能 \(c\) 的 brute-force 结果比较,从而确认整除化简完全正确。
count_range 枚举所有有序边对 \((a,b)\),计算 \(c_{\max}\)、\(g\)、步长 \(d=(a+b)/g\),然后加上允许区间内 \(d\) 的倍数个数。solve_fast 只是在不同的 \(a\) 范围上做并行;从数学上看,每个 \((a,b)\) 的贡献都是独立的。solve_bruteforce 则只保留给检查点使用。
外层只枚举 \(a\) 与 \(b\)。每个 \((a,b)\) 都只做常数次算术,因此总时间大约是
$$O(N^2),$$
远优于直接枚举全部 \((a,b,c)\) 的立方级 brute force。除线程局部计数器外,空间复杂度是 \(O(1)\)。
Дан целочисленный треугольник \(ABC\) с
$$BC \le AC \le AB.$$
Биссектриса угла \(\angle ACB\) пересекает прямую через \(B\), параллельную касательной в точке \(C\) к описанной окружности, в точке \(E\). Нужно посчитать все треугольники с периметром не больше \(100000\), для которых длина \(BE\) является целым числом.
В программе используется
$$a=BC,\qquad b=CA,\qquad c=AB,$$
поэтому условие порядка имеет вид
$$a\le b\le c.$$
Тогда неравенство треугольника и ограничение на периметр дают
$$c < a+b,\qquad a+b+c\le N.$$
Обозначим углы треугольника через \(A,B,C\). Поскольку \(CE\) — биссектриса угла \(\angle C\), имеем
$$\angle ECB=\frac{C}{2}.$$
Прямая через \(B\) параллельна касательной к описанной окружности в \(C\). По теореме о касательной и хорде угол между касательной и хордой \(CB\) равен углу при \(A\). Значит, в треугольнике \(CBE\)
$$\angle CBE = A.$$
Применяя закон синусов в \(CBE\), получаем
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
Следовательно,
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
Теперь используем \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
откуда
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
С другой стороны, по закону синусов в исходном треугольнике,
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
поэтому
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
а также
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
Деление даёт
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
Подставляя это в выражение для \(BE\), получаем ключевую формулу
$$BE=\frac{ac}{a+b}.$$
Нужно, чтобы \(BE\) было целым. Так как \(a,b,c\) уже целые, из формулы выше следует, что это эквивалентно
$$a+b \mid ac.$$
Это и есть решающее упрощение: геометрия полностью исчезает, и остаётся чисто арифметический подсчёт.
Зафиксируем \(a\) и \(b\). Из \(b\le c\), условия \(c<a+b\) и ограничения на периметр следует интервал
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
Если \(c_{\max}<b\), то для такой пары \((a,b)\) треугольников нет.
Положим
$$s=a+b,\qquad g=\gcd(a,b).$$
Так как
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
можно записать
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
Тогда условие
$$s\mid ac$$
становится
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
Поскольку \(a_1\) и \(s_1\) взаимно просты, это эквивалентно
$$s_1 \mid c,$$
то есть
$$\frac{s}{g}\mid c.$$
Следовательно, при фиксированных \((a,b)\) допустимые \(c\) образуют арифметическую прогрессию с шагом
$$d=\frac{a+b}{\gcd(a,b)}.$$
Теперь нужно лишь посчитать кратные \(d\) в интервале \([b,c_{\max}]\). Их количество равно
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
Это заменяет полный внутренний перебор по всем \(c\) формулой времени \(O(1)\).
Код проверяет два разных слоя рассуждения.
Геометрическая проверка. Для тестовых треугольников вроде \((3,4,5)\), \((5,5,8)\), \((7,8,9)\) функция be_from_geometry вычисляет \(BE\) напрямую по координатам и сверяет с
$$\frac{ac}{a+b}.$$
Счётная проверка. Для малых лимитов \(150,300,600\) быстрый арифметический подсчёт сравнивается с brute-force-перебором всех допустимых \(c\). Это подтверждает точность преобразования к делимости.
count_range перебирает упорядоченные пары сторон \((a,b)\), вычисляет \(c_{\max}\), НОД \(g\), шаг \(d=(a+b)/g\) и добавляет разность полов, считающую кратные \(d\) в допустимом интервале. solve_fast распараллеливает только непересекающиеся диапазоны по \(a\); математически вклад каждой пары \((a,b)\) независим. solve_bruteforce сохраняется только для контрольных сравнений.
Внешние циклы идут только по \(a\) и \(b\). Каждая пара даёт лишь константное число арифметических действий, поэтому общая сложность порядка
$$O(N^2),$$
что намного лучше кубического brute-force по всем \((a,b,c)\). Память равна \(O(1)\), не считая локальных счётчиков потоков.
لدينا مثلث صحيح الأضلاع \(ABC\) يحقق
$$BC \le AC \le AB.$$
يقطع منصف الزاوية \(\angle ACB\) المستقيم المار من \(B\) والموازي للمماس عند \(C\) للدائرة المحيطة في النقطة \(E\). المطلوب هو عدّ جميع المثلثات التي لا يتجاوز محيطها \(100000\) والتي تكون فيها القطعة \(BE\) ذات طول صحيح.
يستخدم البرنامج الترميز
$$a=BC,\qquad b=CA,\qquad c=AB,$$
ومن ثم تصبح علاقة الترتيب
$$a\le b\le c.$$
وتعطي متباينة المثلث وقيد المحيط
$$c < a+b,\qquad a+b+c\le N.$$
لنرمز لزوايا المثلث بالرموز المعتادة \(A,B,C\). بما أن \(CE\) منصف للزاوية \(\angle C\)، فإن
$$\angle ECB=\frac{C}{2}.$$
أما المستقيم المار من \(B\) فهو موازٍ للمماس عند \(C\) للدائرة المحيطة. وبحسب مبرهنة المماس والوتر، فإن الزاوية بين هذا المماس والوتر \(CB\) تساوي الزاوية عند \(A\). لذلك في المثلث \(CBE\) نحصل على
$$\angle CBE = A.$$
الآن نطبّق قانون الجيوب في المثلث \(CBE\):
$$\frac{BE}{\sin(C/2)}=\frac{BC}{\sin(A+C/2)}=\frac{a}{\sin(A+C/2)}.$$
ومن ثم
$$BE=a\cdot\frac{\sin(C/2)}{\sin(A+C/2)}.$$
نستخدم بعد ذلك العلاقة \(A+B+C=\pi\):
$$A+\frac{C}{2}=\frac{\pi}{2}+\frac{A-B}{2},$$
وبالتالي
$$\sin\!\left(A+\frac C2\right)=\cos\!\left(\frac{A-B}{2}\right).$$
ومن ناحية أخرى، يعطي قانون الجيوب في المثلث الأصلي
$$a=2R\sin A,\qquad b=2R\sin B,\qquad c=2R\sin C,$$
ومنها
$$a+b=2R(\sin A+\sin B)=4R\cos\!\left(\frac C2\right)\cos\!\left(\frac{A-B}{2}\right),$$
وكذلك
$$c=2R\sin C=4R\sin\!\left(\frac C2\right)\cos\!\left(\frac C2\right).$$
وبقسمة العبارتين نحصل على
$$\frac{a+b}{c}=\frac{\cos((A-B)/2)}{\sin(C/2)}=\frac{\sin(A+C/2)}{\sin(C/2)}.$$
وبالتعويض في الصيغة السابقة نصل إلى الهوية الأساسية
$$BE=\frac{ac}{a+b}.$$
تسأل المسألة متى يكون \(BE\) عددًا صحيحًا. وبما أن \(a,b,c\) أعداد صحيحة أصلًا، فإن الهوية السابقة تجعل ذلك مكافئًا تمامًا للشرط
$$a+b \mid ac.$$
وهذا هو الاختزال الحاسم: تختفي الهندسة تمامًا ويتحول الباقي إلى مسألة عدّ حسابية بحتة.
بعد تثبيت \(a\) و\(b\)، فإن الشرط \(b\le c\) ومتباينة المثلث \(c<a+b\) وقيد المحيط \(c\le N-a-b\) تعطي المجال
$$b \le c \le c_{\max},\qquad c_{\max}=\min(a+b-1,\ N-a-b).$$
إذا كان \(c_{\max}<b\)، فلا يوجد أي مثلث لهذا الزوج \((a,b)\).
لنضع
$$s=a+b,\qquad g=\gcd(a,b).$$
وبما أن
$$\gcd(a,s)=\gcd(a,a+b)=\gcd(a,b)=g,$$
يمكننا أن نكتب
$$a=g a_1,\qquad s=g s_1,\qquad \gcd(a_1,s_1)=1.$$
وعندئذ يصبح الشرط
$$s\mid ac$$
على الصورة
$$g s_1 \mid g a_1 c \quad\Longleftrightarrow\quad s_1 \mid a_1 c.$$
وبما أن \(a_1\) و\(s_1\) أوليان نسبيًا، فهذا يكافئ
$$s_1 \mid c,$$
أي
$$\frac{s}{g}\mid c.$$
إذن قيم \(c\) المقبولة للزوج الثابت \((a,b)\) تشكل متتالية حسابية ذات خطوة
$$d=\frac{a+b}{\gcd(a,b)}.$$
لم يتبقَّ الآن إلا عدّ مضاعفات \(d\) داخل المجال \([b,c_{\max}]\). وعددها يساوي
$$\left\lfloor\frac{c_{\max}}{d}\right\rfloor-\left\lfloor\frac{b-1}{d}\right\rfloor.$$
وهذا يستبدل المسح الداخلي على جميع قيم \(c\) بصيغة زمنها ثابت.
يتحقق الكود من جزأين مختلفين من الاستدلال.
تحقق هندسي. للمثلثات التجريبية مثل \((3,4,5)\) و\((5,5,8)\) و\((7,8,9)\)، تحسب الدالة be_from_geometry القيمة \(BE\) مباشرة من الإحداثيات وتفحص أنها تساوي
$$\frac{ac}{a+b}.$$
تحقق عدّي. للحدود الصغيرة \(150,300,600\)، تُقارن الحصيلة السريعة مع brute force يجرّب جميع قيم \(c\) الممكنة. وهذا يؤكد أن اختزال شرط القسمة دقيق تمامًا.
تدور الدالة count_range على الأزواج المرتبة \((a,b)\)، وتحسب \(c_{\max}\) و\(g\) والخطوة \(d=(a+b)/g\)، ثم تضيف فرق الأرضيات الذي يعد مضاعفات \(d\) داخل المجال المسموح. أما solve_fast فيوازي فقط على مجالات منفصلة من \(a\)؛ ومن الناحية الرياضية فإن مساهمة كل زوج \((a,b)\) مستقلة. وتبقى الدالة solve_bruteforce فقط من أجل المقارنات في نقاط التحقق.
تعمل الحلقتان الخارجيتان فقط على \(a\) و\(b\). وكل زوج يعطي عددًا ثابتًا من العمليات الحسابية، لذا يكون الزمن الكلي تقريبًا
$$O(N^2),$$
وهو تحسن كبير مقارنة بالمسح brute force ذي الكلفة \(O(N^3)\) على جميع الثلاثيات \((a,b,c)\). استهلاك الذاكرة هو \(O(1)\) باستثناء العدادات المحلية الخاصة بالخيوط.