luogu1445 [violet]樱花 阶乘分解

题目大意

求方程$$\frac{1}{x}+\frac{1}{y}=\frac{1}{N!}$$的正整数解的组数。

思路

咱们把式子整理得$$xy-(x+y)N!=0$$。$xy$和$x+y$?貌似可以因式分解?!于是$$N!^2 - (x + y)N! + xy = N!^2$$,即$$(x-N!)(y-N!)=N!^2$$。令$A=x-N!,B=y-N!$,则原式变为$$A*B=(N!)^2$$。因此,解的个数便是$N!^2$的因子的个数。根据唯一分解定理,任意的正整数都可分解为$\prod p_i^{c_i}$,根据阶乘分解的方法,每个$c_i = \sum_{i=1}^{\log_p N}\frac{N}{p^i}$。对于$N!^2$,其质因数分解出的每一个$c_i$都是$N!$质因数分解出的$c_i$的2倍。根据因数个数定理,一个数的因数的个数=$\prod c_i+1$。

综上所述,应当对$N!$进行阶乘分解,再将求出的$2c_i+1$,将对于每一个$p_i$的上式结果相乘即为所求。

注意

本题数字大,因此一切数量值类型都要用long long。

#include <cstdio>
#include <cstring>
using namespace std;

const int MAX_N = 1000010, MAX_P_CNT = 5000, P = 1e9 + 7;

int GetPrime(int *prime, int n)
{
	static bool NotPrime[MAX_N];
	memset(NotPrime, false, sizeof(NotPrime));
	int primeCnt = 0;
	for (int i = 2; i <= n; i++)
	{
		if (!NotPrime[i])
			prime[primeCnt++] = i;
		for (int j = 0; j < primeCnt; j++)
		{
			if (i*prime[j] > n)
				break;
			NotPrime[i*prime[j]] = true;
			if (i%prime[j] == 0)
				break;
		}
	}
	return primeCnt;
}

int Proceed(int n, int *prime)
{
	long long ans = 1;
	for (int i = 0; prime[i] <= n; i++)
	{
		long long k = 0;
		for (long long j = prime[i]; j <= n; j *= prime[i])
			k += (long long)n / j;
		ans = (ans * (k * 2 + 1)) % P;
	}
	return ans;
}

int main()
{
	int n;
	static int prime[MAX_N];
	scanf("%d", &n);
	GetPrime(prime, MAX_N - 1);
	printf("%d\n", Proceed(n, prime));
	return 0;
}

  

posted @ 2018-04-15 21:44  headboy2002  阅读(150)  评论(0编辑  收藏  举报