您的位置:首页 > 其它

佩尔方程

2016-02-17 10:31 190 查看
佩尔方程(Pell Equation)为:

其中d不为完全平方数且d>1.
如果已知它的最小特解:x1,y1

那么存在迭代公式:



通过简单的证明:



由此得到矩阵递推式:



暴力法寻找最小特解:
typedef long long LL;
void search(LL &x,LL &y,LL d){
y=1;
while(1>0){
x=(LL)sqrt(1+d*y*y);
if(x*x-d*y*y==1) break;
y++;
}
}

hdu 3292 No more tricks, Mr Nanguo
http://acm.hdu.edu.cn/showproblem.php?pid=3292

大意:转化题意,即x^2-NY^2=1 求出第K个X解

分析:先暴力法求出特解,然后,Pell方程的解递推矩阵求出答案
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int mod=8191;
struct matrix{
int m[2][2];
}A;
matrix I={
1,0,
0,1
};
void get(int &x,int &y,int n){
for(y=1;;y++){
int sum=n*y*y+1;
x=(int)sqrt(sum);
if(x*x==sum) break;
}
}
matrix multi(matrix a,matrix b){
matrix ans;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
ans.m[i][j]=0;
for(int k=0;k<2;k++){
ans.m[i][j]+=a.m[i][k]*b.m[k][j];
}
ans.m[i][j]%=mod;
}
}
return ans;
}
matrix power(int p){
matrix ans=I,temp=A;
while(p){
if(p&1) ans=multi(ans,temp);
temp=multi(temp,temp);
p>>=1;
}
return ans;
}
int main()
{
int n,k;
while(cin>>n>>k){
int nn=int(sqrt(n));
if(nn*nn==n) {
printf("No answers can meet such conditions\n");
continue;
}
int x,y;
get(x,y,n);
if(k==1){
printf("%d\n",x%mod);
continue;
}
A.m[0][0]=x%mod;  A.m[0][1]=n*y%mod;
A.m[1][0]=y%mod;  A.m[1][1]=x%mod;
A=power(k-1);
printf("%d\n",(A.m[0][0]*x%mod+A.m[0][1]*y%mod)%mod);
}
return 0;
}


连分数:



佩尔方程: 

,随着Y的增大,有关系:

 

因为d不是完全平方数,所以

可写成连分数的形式. 将该连分数表示成


  称之为第n个渐进值。

存在:



POJ 2427 Smith's Problem

http://poj.org/problem?id=2427

大意:求解满足佩尔方程的一对值。数据很大。

连分数求解Pell方程,代码写不出来,参考他人。。

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());
}
}
}

hdu 2281 Square Number

http://acm.hdu.edu.cn/showproblem.php?pid=2281

Find the biggest integer n (1 <= n <= N) and an integer x to make them satisfy



分析:关于平方数之和有一个公式,下面是推导,加深印象。



同时,



所以



所以,上面的等式就等价于:



import java.math.BigInteger;
import java.util.*;

public class Main
{
static BigInteger x,y;
public static void solve(long n)
{
BigInteger limit=BigInteger.valueOf(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*48));
N = BigInteger.valueOf(48);
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){
BigInteger t=p.subtract(BigInteger.valueOf(3)).divide(BigInteger.valueOf(4));
if(t.compareTo(limit)>0) break;
if(t.multiply(BigInteger.valueOf(4)).add(BigInteger.valueOf(3)).equals(p)){
x=t;
y=q;
}
}
g1 = g2;h1 = h2;a1 = a2;
p1 = p2;p2 = p;
q1 = q2;q2 = q;
}
}
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
long val;
while(cin.hasNextLong())
{
val=cin.nextLong();
if(val==0) break;
x=BigInteger.ZERO;
y=BigInteger.ZERO;
solve(val);
System.out.println(x+" "+y);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: