P1445 [Violet]樱花
一句话题意 :
求 \({1 \over x} + {1\over y} = {1\over n!}\) 的解的个数。
很ex 的数学题,考场上没推出来柿子直接爆玲了,可怜。
首先我们把柿子化简一下,变成:
先通分 变成:
\({x+y \over xy} = {1\over n!}\)
十字相乘之后移项可得:
\((x+y) \times n! - xy = 0\)
考试的时候,我推到这里就卡住了,完全不知道下一步怎么去推。
考完看了题解,才发现这是 十字相乘的右边的一部分柿子 就是类似于 \((a+x)(a+y)\) 那样的柿子。
所以,我们给他左右两边同时加上一个 \({n!} ^2\) 变成:
\(n!^2 + (x+y)n! - xy = n!^2\)
之后发现左边的柿子可以化为: \((n! - x) (n!-y) = n!^2\)
也就是 令 \(a = n!-x\) \(b = n!-y\) ,则有 \(ab = n!^2\)
对于每个 \(a,b\) 他对应的 \(x,y\) 是唯一的,因此我们求的是 \(n!^2\) 的因子个数。
有唯一分解定理可得 \(n = p_1^{k1} \times p_2^{k2} ..... \times p_n^{kn}\)
那么我们只需要求出 \(n!\) 的质因子的指数,最后的答案就是每个质因子指数乘二加一,最后在相乘。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int N = 1e6+10;
const int p = 1e9+7;
LL ans = 1;
int n,tot,cnt[N],prime[N];
bool check[N];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s =s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
void YYCH()
{
for(int i = 2; i <= n; i++)
{
if(!check[i])
{
prime[++tot] = i;
}
for(int j = 1; j <= tot && i * prime[j] <= n; j++)
{
check[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
int main()
{
n = read(); YYCH();
for(int i = 1; i <= tot; i++)//枚举每个质数
{
for(LL j = prime[i]; j <= n; j *= prime[i])//质数的 j 次方的因子可以分出 j 个 i
{
cnt[i] += (n/j);
cnt[i] %= p;
}
}
for(int i = 1; i <= tot; i++)
{
ans = (ans * 1LL * (cnt[i] * 2+1)) % p;
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号