zoukankan      html  css  js  c++  java
  • 一本通1624樱花(数学+唯一分解定理)

    #10202. 「一本通 6.2 练习 5」樱花

    题意很简单,就是求给你的那个式子中(x,y)的解得数量。

    但是做起来没那么容易了,基本思路是这样的:

    需要想办法对式子进行整理,进而得到可以解决问题的式子。

    首先把原式进行通分,得到

    进行十字相乘,得到 n!(x+y)=xy ;

    移项,得n!(x+y)-xy=0;

    两边同时加上(n!)2,得到(n!)2-n!(x+y)-xy=(n!)2

    对其进行因式分解,得到(n!-x)(n!-y)=(n!)2

    令a=(n!-x),b=(n!-y),式子变为 ab=(n!)2

    要求组合(x,y)的种数,即变成了求(n!)的因子a的种数,(n!是确定的,那么知道了a的种类数,就知道了b的种类数),

    (n!)2 的因子想到唯一分解定理:n!=p1a1+p2a2+......+pnan ;那么(n!)2=ab=p12a1+p22a2+......+pn2an 

    唯一分解定理中关于因子的个数有cnt=(2×a1+1)×(2×a2+1)×...×(2×an+1) ;

    问题最后就转化成了求(n!)2的因子的个数。

    因为pn为质数,如果暴力求肯定会超时,所以需要素数筛来解决。

    因为n!的每个质因子都不超过n,所以我们可以打表预处理1n内所有质数p,再考虑n!内一共有多少个质因子p。

    唯一分解定理讲解:唯一分解定理

    素数筛讲解:素数筛法讲解 

    代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const ll mod=1e9+7;
     7 const int maxn=1e6+7;
     8 int prime[maxn];
     9 bool isp[maxn];
    10 int cnt;
    11 void makeprime()//预处理素数表 
    12 {
    13     cnt=0;
    14     memset(isp,true,sizeof(isp));
    15     for(int i=2;i<=maxn;i++)
    16     {
    17         if(isp[i])
    18         {
    19         prime[++cnt]=i;
    20         }
    21         for(int j=1;j<=cnt;j++)
    22         {
    23             if(i*prime[j]>maxn)
    24             break;
    25             isp[i*prime[j]]=false;
    26             if(i%prime[j]==0)
    27             break;
    28         }
    29     }
    30     return ;
    31 }
    32 int num[maxn];//用来记录1-n!中每个素数出现的次数 
    33 void makenum(int x)//得到次1-n!中每个素数出现的次数
    34 {
    35     for(int i=1;prime[i]*prime[i]<=x;i++)
    36     {
    37         if(x%prime[i]==0)
    38         {
    39             while(x%prime[i]==0)
    40             {
    41                 num[prime[i]]++;
    42                 x/=prime[i];
    43             }
    44         }
    45     }
    46     if(x>1)
    47     num[x]++;
    48 }
    49 int main()
    50 {
    51     ll n;
    52     cin>>n;
    53     memset(num,0,sizeof(num));
    54     makeprime();
    55     for(int i=1;i<=n;i++)//这里每一个都要处理,因为是n!不是一个数n 
    56     {
    57         makenum(i);
    58     }
    59     ll ans=1;
    60     for(int i=1;i<=n;i++)//唯一分解定理的结论 
    61     {
    62         ans=ans*((ll)num[i]*2+1)%mod;
    63     }
    64     printf("%lld",ans);
    65     return 0;
    66 }
  • 相关阅读:
    RHEL6 建立DVD repo
    stl之std::remove_copy
    分鱼问题
    Nutch的日志系统
    log4j配置文件及nutch中的日志配置
    slf4j教程
    Java中的日期操作
    Avro基础
    【JAVA编码专题】总结
    【JAVA编码专题】深入分析 Java 中的中文编码问题
  • 原文地址:https://www.cnblogs.com/theshorekind/p/12751153.html
Copyright © 2011-2022 走看看