问题 H: Happiness Hotel(佩尔方程)

题目描述

The life of Little A is good, and, he managed to get enough money to run a hotel. The best for him is that he need not go to work outside, just wait for the money to go into his pocket. Little A wants everything to be perfect, he has a wonderful plan that he will keep one most beautiful reception whose size is 1()(which means the reception is 1 square meter). There are other k rooms that have the same area, and the area is x^2(), x is an integer; Little A wants his hotel to be a square. Little A is a good thinker, but not a good maker. As his poor performance on math, he cannot calculate the least area needed to build such a hotel of his will. Now, this task belongs to you, solve this problem to make Little A’s dream of Happy Hotel come true. Please be careful, the whole area should only contain k rooms, and the reception, there should not be any vacant place. 
 

输入

There are several test cases. 

Each case contains only one integer k(1<=k<=1000) ,the number of rooms the hotel should have in one line. 

Proceed to the end of file. 
 

输出

Output one integer d, means the hotel’s area is d^2(If there is no answer, output “no solution”) .The output of one test case occupied exactly one line. 
 

样例输入

1

2

3

样例输出

no solution
3
2

题意分析:

给定小于1000的正整数k, 存在正整数x, d,使得kx^2+1=d^2,求满足条件最小的d。将这个等式调换下位置,就是d^2-kx^2=1,显然是一个佩尔方程(pell方程, pell equation)。所以其实这道题就是求佩尔方程的最小特解。

不过……显然不显然的都不会。就当是记录一下佩尔方程的模板了。

AC代码

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

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNextInt()) {
            int n = in.nextInt();
            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"); // 若为平方数则无解
            } else {
                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);
            }
        }
        in.close();
    }
}

再存个C++的://以下代码段纯属抄袭

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;

int can[1005] = {0};
int a[10005][605]= {0};
int x[6005], y[6005], t[6005];
int h1,h2;
int bb, ee, xx, yy, c, n;
 
void Pell(int ji,int many,int ma,int kk)
{
    if (ji < kk)
        Pell(ji + 1, a[ma][(ji-1)%a[ma][600]+1], ma, kk);
    else
    {
        h1 = 1;
        h2 = 1;
        x[1] = many;
        y[1] = 1;
        return;
    }
    for (int i = 1; i <= h1; i++)
        t[i] = x[i];
    for (int i = 1; i <= h2; i++)
        x[i] = y[i];
    for (int i = 1; i <= h1; i++)
        y[i] = t[i];
    c = h1;
    h1 = h2;
    h2 = c;
    for (int i = 1; i <= h2; i++)
        if (i <= h1)
            x[i] += many * y[i];
        else
            x[i] = many * y[i];
    if (h2 > h1)
        h1 = h2;
    for (int i = 1; i < h1; i++)
        if (x[i] >= 10)
        {
            x[i+1] += x[i] / 10;
            x[i] %= 10;
        }
    while(x[h1] >= 10)
    {
        x[h1+1] = x[h1] / 10;
        x[h1] %= 10;
        h1++;
    }
    x[0] = h1;
}
 
void solve()
{
    int i, j;
    for (j = 1; j <= 31; j++)
        can[j*j] = true;
    for(i = 1; i <= 1000; i++)
    {
        if(!can[i])
        {
            a[i][600]=1;
            bb = 1;
            ee = (int)sqrt((double)i);
            a[i][0] = ee;
            ee =- ee;
            xx = bb;
            yy = ee;
            xx =- yy;
            yy = i - yy * yy;
            n=0;
            while((xx - yy) * (xx - yy) < i || xx >= 0)
            {
                xx -= yy;
                n++;
            }
            a[i][1] = n;
            c = xx, xx = yy, yy = c;
            while(xx != bb || yy != ee)
            {
                a[i][600]++;
                c = xx;
                xx =- yy;
                yy = i - yy * yy;
                yy = yy / c;
                n = 0;
                while ((xx - yy) * (xx - yy) < i || xx >= 0)
                {
                    xx -= yy;
                    n++;
                }
                a[i][a[i][600]] = n;
                c = xx, xx = yy, yy = c;
            }
        }
    }
}
 
int main()
{
    int k;
    solve();
    while(scanf("%d",&k)!=EOF)///ans^2 = k * n ^ 2 + 1,求ans的最小值(k <= 1000)
    {
        if(!can[k])
        {
            if(a[k][600] % 2)
                Pell(1, a[k][0], k, a[k][600]*2);
            else
                Pell(1, a[k][0], k, a[k][600]);
            for (int j = x[0]; j >= 1; j--)
                printf("%d",x[j]);
            printf("\n");
        }
        else
            printf("no solution\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Vitamin_R/article/details/81410247
今日推荐