hdu6222——佩尔方程&&大数__int128
题意
给定一个整数 $N$($1 \leq N \leq 10^{30}$),求最小的整数 $t$,要求 $t \geq N$,使得边长为 $t-1, t, t+1$ 的三角形面积为整数。
分析
根据海伦公式:$S = \sqrt{p(p-a)(p-b)(p-c)}$,$p = \frac{a+b+c}{2}$.
代入,令 $\frac{t}{2}=x$,化简得 $S^2 = 3x^2(x^2-1)$.
题目要求 $S$ 为整数,则 $(x^2-1)$ 一定是3乘以一个平方数,
即 $x^2-1=3y^2$,即 $x^2-3y^2=1$.
易知最小解为(2, 1),用递推式求出其他解即可。
由于题目 $N$ 的范围较大,到 1e30,可以使用 int128(1e38),本地测试1e38内,只有67个解。
#include<bits/stdc++.h> using namespace std; const int maxn = 100+5; __int128 xx[maxn], yy[maxn]; void read(__int128 &x) { x = 0; char ch; int flag = 1; while (ch = getchar()) { if (ch == '-') flag = -1; if (ch >= '0' && ch <= '9') break; } x = ch-'0'; while ((ch = getchar()) >= '0' && ch <= '9') { x = x*10 + ch-'0'; } x *= flag; } void out(__int128 x) { if (x < 0) { x = -x; putchar('-'); } if (x >= 10) out(x / 10); putchar(x % 10 +'0'); } void init() { xx[1] = 2, yy[1] = 1; for(int i = 2;i <= 100;i++) { xx[i] = xx[i-1]*2 + yy[i-1]*3; yy[i] = xx[i-1] + yy[i-1]*2; } } int main() { init(); int T; scanf("%d", &T); while(T--) { __int128 n; read(n); for(int i = 1;i <= 100;i++) { if(xx[i]*2 >= n) { out(xx[i]*2); printf("\n"); break; } } } }
顺便记个int128的模板,🤭🤭
续:
上面的推公式毕竟有点麻烦,
不如先打出符号条件的 $t$,再找规律。
#include<bits/stdc++.h> using namespace std; int main() { for(int t = 2;t < 1000000;t++) { long double p = 3.0*t/2; long double tmp = p*(p-t+1)*(p-t)*(p-t-1); long long s = sqrt(tmp); if(s*s == (long long)tmp) printf("%d ", t); } return 0; }
得到序列:2 4 14 52 194 724 2702 10084 37634.
发现递推式 f[n]=4*f[n-1]-f[n-2]
参考链接:
个性签名:时间会解决一切