JZOJ 3158. 【JSOI2013】丢番图(约数个数)

JZOJ 3158. 【JSOI2013】丢番图

Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits

题目

Description

丢番图是亚历山大时期埃及著名的数学家。他是最早研究整数系数不定方程的数学家之一。

为了纪念他,这些方程一般被称作丢番图方程。最著名的丢番图方程之一是 x n + y n = z n x^n+y^n=z^n xn+yn=zn。费马

提出,对于 n ≥ 2 n≥2 n2 x n + y n = z n x^n+y^n=z^n xn+yn=zn没有正整数解。这被称为“费马大定理”,它的证明直到最近才被安德鲁·怀尔斯(Andrew Wiles)证明。

考虑如下的丢番图方程: 1 / x + 1 / y = 1 / n ( x , y , n ∈ N ∗ ) 1/x+1/y=1/n(x,y,n∈N*) 1/x+1/y=1/n(x,y,nN)

小G对下面这个问题十分感兴趣:对于一个给定的正整数 n n n,有多少种本质不同的解满足方

程?例如 n = 4 n=4 n=4,有三种本质不同 ( x ≤ y ) (x≤y) (xy)的解:

1 / 5 + 1 / 20 = 1 / 4 1/5+1/20=1/4 1/5+1/20=1/4

1 / 6 + 1 / 12 = 1 / 4 1/6+1/12=1/4 1/6+1/12=1/4

1 / 8 + 1 / 8 = 1 / 4 1/8+1/8=1/4 1/8+1/8=1/4

Input

显然,对于更大的 n n n,没有意义去列举所有本质不同的解。你能否帮助小G快速地求出对于给定 n n n,满足方程的本质不同的解的个数?

Output

一行,仅一个整数 n ( 1 ≤ n ≤ 1 0 14 ) n(1≤n≤10^{14}) n1n1014

Sample Input

4

Sample Output

3

Data Constraint

对于30%的数据, n ≤ 1 0 5 n≤10^5 n105.
对于50%的数据, n ≤ 2 31 n≤2^{31} n231.
对于100%的数据, n ≤ 1 0 14 n≤10^{14} n1014.

题解

  • 首先可以确定 x , y x,y x,y的范围, x , y ∈ [ n + 1 , 2 n ] x,yin[n+1,2n] x,y[n+1,2n],这是十分显然的!
  • 一种暴力做法,枚举 x x x,判断是否有可行的 y y y
  • 1 x + 1 y = 1 n frac 1 x+frac 1y=frac1n x1+y1=n1
  • < = > 1 y = x − n n x <=>frac 1y=frac{x-n}{nx} <=>y1=nxxn
  • < = > y = n x x − n <=>y=frac{nx}{x-n} <=>y=xnnx
  • 枚举完后判断 x − n x-n xn是否是 n x nx nx的约数即可。
  • 但这样时间是很慢的,不妨再来推一波式子:
  • 由上面得:
  • y = n x x − n y=frac{nx}{x-n} y=xnnx
  • < = > y ( x − n ) = n x <=>y(x-n)=nx <=>y(xn)=nx
  • 同理可得,
  • x ( y − n ) = n y x(y-n)=ny x(yn)=ny
  • 两式相乘,得
  • x y ( x − n ) ( y − n ) = n 2 x y xy(x-n)(y-n)=n^2xy xy(xn)(yn)=n2xy
  • < = > ( x − n ) ( y − n ) = n 2 <=>(x-n)(y-n)=n^2 <=>(xn)(yn)=n2
  • 这样方案数就是 n 2 n^2 n2的约数个数……吗?
  • 当然不是,因为要求 x ≤ y x≤y xy所以答案要除以 2 2 2
  • n 2 n^2 n2的约数中必然是有 n n n的,这里不会有重复多余的一组答案,
  • 所以最终的答案先加 1 1 1再除以 2 2 2
  • 怎么求 n 2 n^2 n2约数个数?
  • 显然是分解质因数,但当然不用分解 n 2 n^2 n2
  • 分解 n n n就好了,质因数个数全部乘 2 2 2就是 n 2 n^2 n2的每个质因数个数了!
  • 全部加 1 1 1相乘即可得到 n 2 n^2 n2约数个数(小学奥数)。。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
int a[1000010],p[10000010],f[1000010];
int main()
{
	LL n,t;
	int i,j,s=0;
	scanf("%lld",&n);
	t=floor(sqrt(n));
	for(i=2;i<=t;i++) if(!p[i])
	{
		p[i]=1;
		a[++s]=i;
		for(j=2;j<=t/i;j++) p[i*j]=1;
	}
	int k=1;
	while(n>1&&k<=s)
	{
		while(n%a[k]==0) 
		{
			n/=a[k];
			f[k]++;
		}
		k++;
	}
	LL ans;
	if(n>1) ans=3; else ans=1;
	for(i=1;i<=s;i++) ans=ans*(f[i]*2+1);
	printf("%lld",ans/2+1);
	return 0;
}
哈哈哈哈哈哈哈哈哈哈
原文地址:https://www.cnblogs.com/LZA119/p/13910082.html