#886.「Violet5」 樱花

题意概括:

题目意思很明白,输入一个 i n t int int类型整数 n n n ( 1 < = n < = 1 0 6 1<=n<=10^6 1<=n<=106 ) 求方程 1 x + 1 y = 1 n ! \frac{1}{x}+\frac{1}{y}=\frac{1}{n!} x1+y1=n!1 ( n ! n! n! 表示 n n n 的阶乘,即 n ! = 1 × 2 × 3 × ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ × n n!=1\times2\times3\times······\times n n!=1×2×3×⋅⋅⋅⋅⋅⋅×n ) 解的个数

题目分析:

肯定是一个数论题~~(废话)~~,题目中的方程直接枚举是 O ( n 3 ) O(n^3) O(n3) 的时间复杂度,绝对会 T L E TLE TLE ,那么就对方程进行分析:
1 x + 1 y = 1 n ! 设 n ! = k , \begin{aligned} & \frac{1}{x} + \frac{1}{y} = \frac{1}{n!}\\ & 设 n!=k,\\ \end{aligned} x1+y1=n!1n!=k
第一眼看上去, x x x y y y 都是一次的整数,只有 n ! n! n! 是一个式子,所以用一个未知数代替,方便运算和思考。其实就是我懒对原方程进行化简,我习惯把 x x x 当作主元,用 y y y 也可以。把 y y y k k k 当作一个常数,用解普通方程的步骤去解。
∴ 1 x + 1 y = 1 k 1 x = 1 k − 1 y 1 x = y k y − k k y 1 x = y − k k y x = k y y − k \begin{aligned} & \therefore \frac{1}{x} + \frac{1}{y} = \frac{1}{k}\\ & \frac{1}{x} = \frac{1}{k} - \frac{1}{y}\\ & \frac{1}{x} = \frac{y}{ky} - \frac{k}{ky}\\ & \frac{1}{x} = \frac{y-k}{ky}\\ & x = \frac{ky}{y-k}\\ \end{aligned} x1+y1=k1x1=k1y1x1=kyykykx1=kyykx=ykky
这时,无法对方程继续化简,但分式上下都有 y y y k k k ,所以可以考虑再设一个关于 y y y k k k 的未知数,去表达 y y y k k k 的关系。
设 y − k = p , ∴ y = k + p \begin{aligned} & 设 y-k = p,\\ & \therefore y = k + p\\ \end{aligned} yk=py=k+p
找到之后,就可以把 y = k + p y=k+p y=k+p 代入方程,得到
∴ x = k ( k + p ) p ∴ x = k + k 2 p \begin{aligned} & \therefore x = \frac{k(k+p)}{p}\\ & \therefore x = k+\frac{k^2}{p}\\ \end{aligned} x=pk(k+p)x=k+pk2
解出 x x x 的值后,观察式子,发现可以运用文化课上讲过的整数的性质,
∵ x , k = n ! 为正整数 ∴ p ∣ k 2 ∴ y − n ! ∣ ( n ! ) 2 ∴ ( y − n ! ) 为 ( n ! ) 2 的因子 ∴ ( y − n ! ) 为 n ! 的因子 ∵ y , n ! 为正整数 ∴ x 为正整数 ∴ 只要 ( y − n ! ) 为 n ! 的因子,就有原方程的一组解 \begin{aligned} & \because x,k=n!为正整数\\ & \therefore p \mid k^2\\ & \therefore y-n! \mid (n!)^2\\ & \therefore (y-n!) 为(n!)^2的因子\\ & \therefore (y-n!) 为n!的因子\\ & \because y,n!为正整数\\ & \therefore x为正整数\\ & \therefore 只要(y-n!)为n!的因子,就有原方程的一组解\\ \end{aligned} xk=n!为正整数pk2yn!(n!)2(yn!)(n!)2的因子(yn!)n!的因子yn!为正整数x为正整数只要(yn!)n!的因子,就有原方程的一组解
通过分析,就可以把原问题转化为求 n ! n! n!的因子数

代码实现

由唯一分解定理,我们只需要解出n!的质因数,balabala的一个埃氏筛函数

int primes[1000005];//记录质因数
bool st[1000005];//标记是否为质数
int cnt;
int n;
long long ans=1;
void prime_set(int n){
    st[1]=1;
    for (int i=2;i<=n;i++){
        if (!st[i])
            primes[++cnt]=i;
        for (int j=1;j<=cnt&&primes[j]*i<=n;j++){
            st[primes[j]*i]=1;
            if (i%primes[j]==0){
                break;
            }
        }
    }
}

通过唯一分解定理的另一个公式,即
n 的因子数 = ∏ i = 0 质因子个数 质因子 i 的个数 + 1 n的因子数=\prod\limits_{i=0}^{质因子个数}质因子i的个数+1 n的因子数=i=0质因子个数质因子i的个数+1
就可以得到答案了

prime_set(n);
for (int i = 1; i <= cnt; i++){
    int s = 0;
    for (int j=n;j;j/=primes[i]){
        s+=j/primes[i];
    }
    ans=1ll*ans*(s<<1|1)%P;//1ll用来防止数据溢出
}
printf("%lld",ans);

Code

#include<bits/stdc++.h>
#define P 1000000007
using namespace std;
int primes[1000005];
bool st[1000005];
int cnt;
int n;
long long ans=1;
void prime_set(int n){
    st[1]=1;
    for (int i=2;i<=n;i++){
        if (!st[i])
            primes[++cnt]=i;
        for (int j=1;j<=cnt&&primes[j]*i<=n;j++){
            st[primes[j]*i]=1;
            if (i%primes[j]==0){
                break;
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    prime_set(n);
    for (int i = 1; i <= cnt; i++){
        int s = 0;
        for (int j=n;j;j/=primes[i]){
            s+=j/primes[i];
        }
        ans=1ll*ans*(s<<1|1)%P;
    }
    printf("%lld",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值