设的渐近分数列,由连分数理论知存在使得(pi,qi)为佩尔方程的解。取其中最小的,将对应的 (pi,qi)称为佩尔方程的基本解,或最小解,记作(x1,y1),则所有的解(xi,yi)可表示成如下形式:
。
或者由以下的递回关系式得到:
。
1)暴力枚举y的值,对等式做判定
2)通过的连分数表示确定最小解
连分数构造方法:
1)求最小特解
POJ :3292
import java.math.BigInteger;
import java.util.Scanner;
public class Main
{
public static void solve(int n)
{
BigInteger N, p1, p2, q1, q2, a0, a1, a2, g1, g2, h1, h2,p,q;
g1 = q2 = p1 = BigInteger.ZERO;
h1 = q1 = p2 = BigInteger.ONE;
a0 = a1 = BigInteger.valueOf((int)Math.sqrt(1.0*n));
BigInteger ans=a0.multiply(a0);
if(ans.equals(BigInteger.valueOf(n)))
{
System.out.println("No solution!");
return;
}
N = BigInteger.valueOf(n);
while (true)
{
g2 = a1.multiply(h1).subtract(g1);
h2 = N.subtract(g2.pow(2)).divide(h1);
a2 = g2.add(a0).divide(h2);
p = a1.multiply(p2).add(p1);
q = a1.multiply(q2).add(q1);
if (p.pow(2).subtract(N.multiply(q.pow(2))).compareTo(BigInteger.ONE) == 0) break;
g1 = g2;h1 = h2;a1 = a2;
p1 = p2;p2 = p;
q1 = q2;q2 = q;
}
System.out.println(p+" "+q);
}
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
while(cin.hasNextInt())
{
solve(cin.nextInt());
}
}
}
2)求第K解 HDU 3292
求出特解后,进行矩阵快速幂(注意当d为完全平方数时只有平凡解 )。
第K解:
code:
#include
using namespace std;
//#define N 100010
#define LL long long
#define PB push_back
#define pii pair
#define MP make_pair
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 3e5 + 10;
const int mod = 8191;
struct mat
{
int s[2][2];
};
mat mul(mat a, mat b)
{
mat c;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++){
c.s[i][j] = 0;
for (int k = 0; k < 2; k++)
{
c.s[i][j] += a.s[i][k] * b.s[k][j];
c.s[i][j] %= mod;
}
}
return c;
}
mat qpow(mat a, int b)
{
mat c;
c.s[0][0] = c.s[1][1] = 1;
c.s[1][0] = c.s[0][1] = 0;
while (b)
{
if (b & 1)
c = mul(c, a);
a = mul(a, a);
b >>= 1;
}
return c;
}
pii solve(ll n)
{
ll N, p1, p2, q1, q2, a0, a1, a2, g1, g2, h1, h2, p, q;
g1 = q2 = p1 = 0;
h1 = q1 = p2 = 1;
a0 = a1 = sqrt(n * 1.0);
ll ans = a0 * a0;
N = n;
// cout<