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; }