广东工业大学ACM程序设计大赛 等式

题目链接:点击打开链接

题意:给定n,求1/x + 1/y = 1/n (x<=y)的解数。(x、y、n均为正整数)

题解:首先看一下最直观的思路。两层for循环去暴力去找x和y。然后用个ans来统计。时间复杂度太高。会时间超限。

那么就去考虑有没有什么优化。

然后我们发现除了去变形这个式子就没有其他方法了。

1/x+1/y=1/n

-->   两边乘上xyn,这一步很容易想到。

nx+ny=xy

-->  因为x,y,n为正整数,所以n > y >= x ,一定存在x = n-a,y = n - b。带入式子化简。这一步能想到简直是玄学!!

b*a=n*n。

观察式子。我们很容易看出来,a和b是n*n的两个因子且a>b。那么问题就变成了。n*n的因子的所有的组合方式了。

那么问题了。如何求某个数的因子。

那么约数定理出现了:

n可以 分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak,
由约数定义可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1 ,共(a1+1)个;同理p2^a2的 约数有(a2+1)个......pk^ak的约数有(ak+1)个。
故根据 乘法原理:n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)。

然后就代码如下:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;

int num[64];

int main(){
	int cases , t = 0;
	scanf("%d",&cases);
	while(cases--){
		int n,p = 0;
		memset(num,0,sizeof(num)); // num数组类似桶排序。只存某个质因子出现了几次。不存具体数 
		cin >> n;
		for(int i = 2 ; i * i<= n ; i++){  // 解释一下为什么为什么要 i*i <= n . 能过滤很多没用的因素 
			if(n %i == 0){
				while(n%i == 0){
					num[p]++;
					n /= i;
				}
				p++;
			}
		}
		if(n != 1){ // 若n为质数。那么他除了自己的没有其他质因子。 
			num[p]++;
			p ++;
		}
		for(int i = 0 ; i < p ; i ++) // 每个因子乘二原因是。我们算的n的因子而不是n方的。n方的质因子的种类和n一样但是个数比n多一倍 
			num[i] *= 2;
		int ans = 1;
		for(int i = 0 ; i < p ; i ++)
			ans *= (num[i] + 1);
		cout << (ans + 1)/2 << endl;  // +1 的原因是消除奇数和偶数的影响。 除2是因为 x < y有重复的。 
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值