Special Solution of Perl Equation by Continuous Fraction Method

Reprinted from https://blog.csdn.net/wh2124335/article/details/8871535?locationNum=14&fps=1

1. Forms of the Perl equation:

$$x^2-Dy^2=1, \D is a positive integer $$

2. Special Solutions to the Perl Equation

The special solution refers to the smallest integer solution of the Perl equation, and it is easy to find that y also reaches the minimum when x is the smallest.

In general, the special solution of the Perl equation is obtained by the windfall enumeration method. This paper describes how to use the continuous fraction method to solve the special solution.

This article will not cover proof, only the method.

3. Continuous fraction method

A simple continuous fraction representation of a real number means that a real number is represented by the following methods:

$$x = a_0+\frac{1}{a_1 + \frac{1}{a_2+\frac{1}{a_3+...}}}$$

You can abbreviate the continuous score as: $x = [a_0;a_1, a_2, a_3...]$.

There are two forms of continuous fractions of rational numbers:

$$\frac{p}{q} = [a_0; a_1, a_2, a_3,..., a_N, 1] or [a_0; a_1, a_2, a_3,..., a_N+1]$$

All infinite consecutive fractions are unreasonable numbers, and all unreasonable numbers can be expressed as infinite consecutive fractions in an accurate way, which can be used to approximate the value of the unreasonable number.

3. Continuous fractional representation of the square root of an incomplete square number

It can be proved that the square root of an incomplete square number is periodic:

For example:

Short form:

$$\sqrt 22 = [4;1,2,4,2,1,8]$$

After that there will be a cycle of 1,2,4,2,1,8

We might as well remember this form of continuous fraction as follows:

$$\sqrt22 = [4;<1,2,4,2,1,8>]$$

Obviously the length of the loop section is 6

And there's another important feature: this section must be $a_1$to start and last $a_n$must be $a_Twice as much as $0.

5. The smallest special solution of the Perl equation:

We write $\sqrt D$as a continuous fraction: (equivalent to wireless square root approximation with a continuous fraction)

 $$\sqrt D =  [a_0;<a_1, a_2, ..., a_{n-1},2a_0>]$$

And we remember:

$$\frac{p}{q} = [a_0; a_1, a_2, ..., a_{n-1}]$$

(For calculating p,q: as long as the continuous fraction is expanded, the iteration is sufficient)

Where if the length of the loop section is s

So here's the conclusion:

1. If s is even.The minimum special solution is:

$$x_0 = p, y_0 = q$$

2. If s is odd, the minimum special solution is:

$$x_0 = 2p^2+1, y_0 = 2pq$$

6. Calculate the consecutive fraction of $\sqrt D$

We want to get an accurate contiguous fraction expansion, so the key is not to use floating point calculations.

Next, for example, $\sqrt {22}$

 

In this way, we computed the contiguous score: $\sqrt {22} = [4;<1,2,4,2,1,8>]$.

Then it can be calculated:

$$\frac{197}{42} = [4;1,2,4,2,1]$$

Since the length of the loop section 6 is an even number, the minimum special solution of the Perl equation $x^2 -22y^2 = 1 $is: $x_0 = 197, y_0 = 42$.

Then, referring to the example above, it is easy to design an algorithm for calculating the continuous fraction.

Code

The result is very large. Many results are longer than long within 1000.Change to a large number.

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
ll a[20000];
bool pell_minimum_solution(ll n,ll &x0,ll &y0){
    ll m=(ll)sqrt((double)n);
    double sq=sqrt(n);
    int i=0;
    if(m*m==n)return false;//When n Is the complete square number then the Perl equation has no solution
    a[i++]=m;
    ll b=m,c=1;
    double tmp;
    do{
        c=(n-b*b)/c;
        tmp=(sq+b)/c;
        a[i++]=(ll)(floor(tmp));
        b=a[i-1]*c-b;
        //printf("%lld %lld %lld\n",a[i-1],b,c);
    }while(a[i-1]!=2*a[0]);
    ll p=1,q=0;
    for(int j=i-2;j>=0;j--){
        ll t=p;
        p=q+p*a[j];
        q=t;
        //printf("a[%d]=%lld %lld %lld\n",j,a[j],p,q);
    }
    if((i-1)%2==0){x0=p;y0=q;}
    else{x0=2*p*p+1;y0=2*p*q;}
    return true;
}
 
int main(){
    ll n,x,y;
    while(~scanf("%lld",&n)){
        if(pell_minimum_solution(n,x,y)){
            printf("%lld^2-%lld*%lld^2=1\t",x,n,y);
            printf("%lld-%lld=1\n",x*x,n*y*y);
        }
    }

A java table code:

import java.io.*;
import java.math.*;
import java.util.*;
 
public class main {
    static long [] a = new long [1000];
    static BigInteger x;
    static BigInteger y;
    public static void main(String [] args) throws FileNotFoundException{
        FileReader fin = new FileReader ("data.in");
        File fout = new File("data.out");
        PrintStream pw = new PrintStream(fout);
        Scanner cin = new Scanner(fin);
        System.setOut(pw);
        while(cin.hasNext()){
            long n=cin.nextLong();
            if(pell_solution(n)){
                
                System.out.print("\""+x+"\",");
            }else{
                System.out.print("\"no solution\",");
            }
        }
    }
    public static boolean pell_solution(long D){
        double sq=Math.sqrt((double)D);
        long m=(long) Math.floor(sq);
        int i=0;
        if(m*m==D)return false;
        a[i++]=m;
        long b=m,c=1;
        double tmp;
        do{
            c=(D-b*b)/c;
            tmp=(sq+b)/c;
            a[i++]=(long)(Math.floor(tmp));
            b=a[i-1]*c-b;
        }while(a[i-1]!=2*a[0]);
        BigInteger p=new BigInteger("1");
        BigInteger q=new BigInteger("0");
        BigInteger t;
        for(int j=i-2;j>=0;j--){
            t=p;
            p=q.add(p.multiply(BigInteger.valueOf(a[j])));
            q=t;
        }
        if((i-1)%2==0){
            x=p;y=q;
        }else{
            x=BigInteger.valueOf(2).multiply(p).multiply(p).add(BigInteger.ONE);
            y=BigInteger.valueOf(2).multiply(p).multiply(q);
        }
        return true;
    }
}
View Code

Tags: Java

Posted on Thu, 21 May 2020 21:19:41 -0400 by jimson