Comet OJ - Contest #0 A题 解方程 (数学)
题目描述
小象同学在初等教育时期遇到了一个复杂的数学题,题目是这样的:
给定自然数 nn,确定关于 x, y, zx,y,z 的不定方程 \displaystyle \sqrt{x - \sqrt{n}} + \sqrt{y} - \sqrt{z} =0x−n
当时的小象同学并不会做这道题。多年后,经过高等教育的洗礼,小象同学发现这道题其实很简单。小象同学认为你一定也会做这道题,所以把这道题留给了你。为了便于输出,你不需要输出每一组解 (x, y, z)(x,y,z),你只需要给出解的数量和所有解的 x y zxyz 之和对 (10^9+7)(109+7) 取模的值即可。注意,解的数量不对 (10^9+7)(109+7) 取模。
输入描述
输入包含多组测试数据。输入的第一行包含一个正整数 TT (1 \leq T \leq10^41≤T≤104),表示测试数据的组数。接下来依次描述每组测试数据,对于每组测试数据:
仅一行,包含一个非负整数 nn (0 \leq n \leq 2 \times 10^90≤n≤2×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'; } } }