【洛谷 P1445】[Violet]樱花

更好的阅读体验

传送门

【题目】

求方程\(\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\)的正整数解的组数,其中\(n\leq10^{6}\)
解的组数,应模\(1e9+7\)

输入格式:

输入一个整数\(n\)

输出格式:

输出答案。

【Input】

1439

【Output】

102426508

【分析】

首先看到这个方程:
\[ \frac{1}{x}+\frac{1}{y}=\frac{1}{n!} \]
将左边通分后并将分子分母调换:
\[ \frac{xy}{x+y}=n! \]
再将\(x+y\)移到右边并两边同时乘以\(2\)
\[ x(2n!-y)+y(2n!-x)=0 \]
由此可得除非\(x\)\(y\)都等于\(2n!\),否则其中必有一个是大于\(2n!\)的。那么我们假设\(x\)是大于\(2n!\)的,则易知\(x>2n!>y>n!\)
假设\(y=n!+k\)\(k\)为正整数),由上面的式子可以推出:
\[ \frac{x-2n!}{x}=\frac{n!-k}{n!+k} \]
于是:
\[ x=\frac{n!^{2}}{k}+n! \]
\(x>2n!\)\(x\)为正整数,所以
\[ \frac{n!}{k}>1 \]
这里我们就可以知道\(k\)必须取\(n!\)的约数,且\(k\)不能等于\(n!\)。于是我们只要求出\(n!\)的约数个数并减去\(n!\)这个约数即可,但我们之前是假设\(x>y\),所以约数还要乘\(2\)
\(n!\)的约数要怎么求可以自行百度。

【代码】

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
bool prime[1000001];
void primes(){  //预处理所有质数 
    memset(prime,1,sizeof(prime));
    prime[0] = 0;
    prime[1] = 0;
    for(int i=2;i<1000001;i++){ //埃氏筛 
        if(prime[i]){
            for(int j=i+i;j<1000001;j+=i){
                prime[j]=0;
            }
        }
    }
}
int cal(int n,int p){   //用来计算n!的约数个数 
    if(n<p) return 0;
    else return n/p+cal(n/p,p);
}
int main(){
    primes();
    int n;
    scanf("%d",&n); 
    int i=2;
    ll cnt=1;
    while(i<=n){
        if(prime[i])
            cnt=(ll)cnt*((2*cal(n,i)+1)%mod)%mod;   //一边计算,一边取模 
        i++;
    }
    printf("%lld",cnt); //输出答案 
    return 0;
}

转载于:https://www.cnblogs.com/hlw1/p/11020122.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值