c语言求佩尔方程的解,佩尔方程

佩尔方程(Pell Equation)为:

b88015c806138cfbbe1b38812a23bdfb.png 其中d不为完全平方数且d>1.

如果已知它的最小特解:x1,y1

那么存在迭代公式:

通过简单的证明:

293c1e7259b8180eac3dd64c51cbf178.gif

由此得到矩阵递推式:

暴力法寻找最小特解:

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

#include

#include

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

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

同时,

e2581c7a7a56cafa9fb23c36eef191e8.gif

所以

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

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

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值