Comet OJ - Contest #0 A题 解方程 (数学)

题目描述

 

小象同学在初等教育时期遇到了一个复杂的数学题,题目是这样的:

给定自然数 nn,确定关于 x, y, zx,y,z 的不定方程 \displaystyle \sqrt{x - \sqrt{n}} + \sqrt{y} - \sqrt{z} =0xn+yz=0 的所有自然数解。

当时的小象同学并不会做这道题。多年后,经过高等教育的洗礼,小象同学发现这道题其实很简单。小象同学认为你一定也会做这道题,所以把这道题留给了你。为了便于输出,你不需要输出每一组解 (x, y, z)(x,y,z),你只需要给出解的数量和所有解的 x y zxyz 之和对 (10^9+7)(109+7) 取模的值即可。注意,解的数量不对 (10^9+7)(109+7) 取模。

 

 
 

输入描述

 

输入包含多组测试数据。输入的第一行包含一个正整数 TT (1 \leq T \leq10^41T104),表示测试数据的组数。接下来依次描述每组测试数据,对于每组测试数据:

仅一行,包含一个非负整数 nn (0 \leq n \leq 2 \times 10^90n2×109),含义如题面所示。

 

输出描述

 

对于每组数据,输出一行。若方程有无穷多组自然数解,则在这一行输出 \text{``infty''}“infty”(不含引号),否则在这一行输出两个整数,其中第一个整数表示方程的解数,第二个整数表示所有解的 x y zxyz 之和对 (10^9+7)(109+7) 取模的值,这两个整数之间用恰好一个空格隔开,行末不要有多余的空格。

 

样例输入 1 

3
6
12
24

样例输出 1

0 0
1 12
2 72

提示

当 n = 12n=12 时,方程唯一的解为 x = 4x=4, y = 1y=1, z = 3z=3。

当 n = 24n=24 时,方程的两组解为 x = 5x=5, y = 2y=2, z = 3z=3 和 x = 7x=7, y = 1y=1, z = 6z=6。

 

思路:

移项,sqrt( x- sqrt(n) ) = sqrt(z)-sqrt(y)

两边平方(因为来说让求的就是自然数解,所以平方不会影响结果,。)

x-sqrt(n) =  z+y- 2*sqrt( z*y)

移项:

x-(z+y) = sqrt(n)-sqrt(4*z*y)

我们来分类讨论一波,

当n是一个平方数,

即 sqrt(n)是一个有理数,设m = sqrt(n)

那么我们令y或z任意一个为0,得如下(比如y=0)

x-z= m

显然上表达式是一个无穷解的不定方程。

可以得出结论,当n是一个平方数,那么有无穷解。

我们再来看 sqrt n 是一个无理数的时候,

想让方程成立,必须要满足 下面的两个条件

n=4*y*z

x=z+y

 

那么我们就可以直接枚举n/4的因子来得出我们的答案。

 

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
const ll mod=1e9+7;
int main()
{
    //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
    //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    int t;
    gbtb;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int k=sqrt(n);
        if(k*k==n)
        {
            cout<<"infty"<<endl;
        }else
        {
            int cnt=0;
            ll ans=0ll;
            if((n%4)==0)
            {
                n/=4;
                int x,y,z;
                int m=sqrt(n);
                for(int i=1;i<=m;i++)
                {
                    if((n%i)==0)
                    {
                        y=i;
                        z=n/i;
                        x=y+z;
                        ans+=1ll*x*y*z;
                        ans%=mod;
                        cnt++;
                    }
                }
                cout<<cnt<<" "<<ans<<endl;
            }else
            {
                cout<<"0 0"<<endl;
            }
        }
    }
    
    
    
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

 

posted @ 2019-05-17 19:32  茄子Min  阅读(341)  评论(0编辑  收藏  举报