A.解方程---Comet OJ - Contest #0

解方程

题目链接https://www.cometoj.com/contest/34/problem/A?problem_id=1473

题目描述

小象同学在初等教育时期遇到了一个复杂的数学题,题目是这样的:
在这里插入图片描述
当时的小象同学并不会做这道题。多年后,经过高等教育的洗礼,小象同学发现这道题其实很简单。小象同学认为你一定也会做这道题,所以把这道题留给了你。为了便于输出,你不需要输出每一组解 (x, y, z),你只需要给出解的数量和所有解的 x y z 之和对 (10^9+7) 取模的值即可。注意,解的数量不对 (10 ^9+7)取模。

输入描述

输入包含多组测试数据。输入的第一行包含一个正整数 T (1≤T≤10 4),表示测试数据的组数。接下来依次描述每组测试数据,对于每组测试数据:
仅一行,包含一个非负整数 n (0≤n≤2×109
输出描述

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

样例输入 1

3
6
12
24

样例输出 1

0 0
1 12
2 72

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

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


我们可以先简化一下,移项平方后可得:
在这里插入图片描述
现在可以进行一个简单的分类讨论:
1.sqrt(n)是有理数:
在这里插入图片描述
2.sqrt(n)是无理数:
在这里插入图片描述
当然,从上式也可得出y<=z,因为
是一个正数是一个正数
分析完成之后就比较好办了:
判断是否为有理数:

扫描二维码关注公众号,回复: 6098215 查看本文章
int qx=sqrt(x);
if (qx*qx==x) {
	printf ("infty\n");
	continue;
}

无理数的第一个式子:n=4yz

if (x%4) ans=0,sum=0;
printf ("%d %d\n",ans,sum);	

接下来就是暴力枚举z和y了:

x/=4;
for (int i=1; i<=qx/2; i++) {
	int p=x/i;
	if (p*i==x && (i+p)>qx) {
		ans++;
		sum=(sum+((long long)x*(i+p))%mod)%mod;
	}
}

当然最重要的一点就是如果用这种暴力的方法的话就千万别全用long long,否则会超时,QAQ我一直TLE,问过之后大佬们说long long 是int 的两倍时间。。。
以下是详细代码:

#include <cstdio>
#include <cmath>
const int mod=1e9+7;
int ans=0,sum=0;
int main() {
	int t,x;
	scanf ("%d",&t);
	while (t--) {
		scanf ("%d",&x);
		ans=sum=0;
		int qx=sqrt(x);
		if (qx*qx==x) {
			printf ("infty\n");
			continue;
		}
		else if (x%4) ans=0,sum=0;
		else {
			x/=4;
			for (int i=1; i<=qx/2; i++) {
				int p=x/i;
				if (p*i==x && (i+p)>qx) {
					ans++;
					sum=(sum+((long long)x*(i+p))%mod)%mod;
				}
			}
		}
		printf ("%d %d\n",ans,sum);	
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43906000/article/details/89046307