zoukankan      html  css  js  c++  java
  • 「一本通 6.2 练习 5」樱花

    求不定方程  $ frac{1}{x}+frac{1}{y}=frac{1}{n!} $ 的正整数解$(x,y) $的数目.

    analysis

    首先先得化简式子,因为这个式子确实看不出来什么

    一般看到的题解里有这两种化法:

    first:

    $frac{1}{x}+frac{1}{y}=frac{1}{n!}$

    $frac{xy}{x+y}=n!$

    $xy=n!(x+y)$

    $-n!(x+y)+xy=0leftarrow ightarrow(n!x+n!y)-xy=0$

    对数学敏感的同学相信写到这一步时就已经可以发现一些东西了,这个式子是十字相乘法拆开括号的后两项!


    若设$a=-n!,b=x,c=y$,则$a(b+c)+bc=0$,等式两边同时加上$a^2$

    则$a^2+a(b+c)+bc=a^2,(a+c)(a+b)=a^2$


    于是有$(x-n!)(y-n!)=(n!)^2$

    也就是说$(x-n!)|(n!)^2$

    那么,$(x-n!)$等价于$(n!)^2$的因子,又由于$(x-n!)$和x的个数相等,那么x的个数和$(n!)^2$的因子的个数一一对应

    second:

    设$y=n!+k$

    则原方程为$x(n!+k)=n!(x+(n!+k))$

    即$xn!+xk=n!(x+n!+k),xn!+xk=n!x+(n!)^2+n!k$

    也就是$x=frac{(n!)^2}{k}+n!$

    也就是说x的个数等于$(n!)^2$的因子的个数


    那么本题就是求$(n!)^2$的因子的个数

    求因子个数,根据唯一分解定理的推论:

    $x=prod_{i=1}^{m}p_i^{s_i},p_i$是素数

    x的约数个数$d(n)=prod_{i=1}^{m}(s_i+1)$根据乘法原理可证明

    对$ n! $ 唯一分解时可以用暴力,复杂度是$ O(sum_{i=1}^{n} sqrt{n}) $,应该是能过的.

    但是上面的复杂度有点高,这里有更简单的方法.

        for(int i=1;i<=p[0];++i){
            for(LL j=p[i];j<=n;j*=p[i]) c[i]+=(n/j);
            c[i]%=mo;
        }

    这么做为什么是对的呢?自已手动模拟一下就行了.还是要记住这个的.

    总结,在遇到等式问题时,要多把等式转化为乘法形式,这样得到的信息比加法要多.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int mo=1000000007;
    int n,p[1000006];
    LL c[1000006];
    bool vis[1000006];
    void get_prime(){
        for(int i=2;i<=n;++i){
            if(!vis[i])
                p[++p[0]]=i;
            for(int j=1;j<=p[0]&&1LL*i*p[j]<=n;++j){
                vis[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    int main(){
        scanf("%d",&n);
        get_prime();
        for(int i=1;i<=p[0];++i){//重点:求1~n之间约数的次幂 
            for(LL j=p[i];j<=n;j*=p[i]) c[i]+=(n/j);
            c[i]%=mo;//记住上面那个公式 
        }
        LL ans=1;
        for(int i=1;i<=p[0];++i)
        ans=(ans*(c[i]<<1|1))%mo;
        printf("%lld
    ",ans);
        return 0;
        
    }

    暴力算法

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int mo=1000000007;
    int n,p[1000006],id[1000006];
    LL c[1000006];
    bool vis[1000006];
    void get_prime(){
        for(int i=2;i<=n;++i){
            if(!vis[i]){
                p[++p[0]]=i;
                id[i]=p[0];
            }
            for(int j=1;j<=p[0]&&1LL*i*p[j]<=n;++j){
                vis[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    int main(){
        scanf("%d",&n);
        get_prime();
        for(int i=1;i<=n;++i){
            int x=i;
            for(int j=1;j<=p[0];++j){
                if(1LL*p[j]*p[j]>x) break;
                while(x%p[j]==0) c[j]++,x/=p[j];
            }
            if(x>1) c[id[x]]++;  
        }
        LL ans=1;
        for(int i=1;i<=p[0];++i)
        ans=(ans*(c[i]<<1|1))%mo;
        printf("%lld
    ",ans);
        return 0;
        
    }

  • 相关阅读:
    04-老马jQuery教程-DOM节点操作及位置和大小
    03-老马jQuery教程-DOM操作
    02-老马jQuery教程-jQuery事件处理
    01-老马jQuery教程-jQuery入口函数及选择器
    08Vue.js快速入门-Vue综合实战项目
    09Vue.js快速入门-Vue入门之Vuex实战
    07Vue.js快速入门-Vue路由详解
    06Vue.js快速入门-Vue组件化开发
    整套高质量前端基础到高级视频教程免费发布
    05-Vue入门系列之Vue实例详解与生命周期
  • 原文地址:https://www.cnblogs.com/huihao/p/11742058.html
Copyright © 2011-2022 走看看