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]

 

 

参考链接:

1. https://blog.csdn.net/alusang/article/details/81266923

2. https://leflacon.github.io/a1e708e2/

posted @ 2019-10-10 22:46  Rogn  阅读(554)  评论(0编辑  收藏  举报