• 济南学习D3T1__线性筛和阶乘质因数分解


    【问题描述】

    从1− N中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少。

    【输入格式】

    第一行一个数字N。

    【输出格式】

    一行,一个整数代表答案对100000007取模之后的答案。

    【样例输入】

    7

    【样例输出】

    144

    【样例解释】

    但是塔外面有东西。

    【数据规模与约定】

    对于20%的数据,1<=N<=100。

    对于50%的数据,1<=N<=5000。

    对于70%的数据,1<=N<=10^5。      

    对于100%的数据,1<=N<=5*10^6。

     ________________________________________________________________

    这个题并没有太好的办法,后来看了题解,才知道对N的阶乘进行质因数分解。于是用了筛法和快速幂,可是超时,只过了60分。于是学习了线性快速幂,时间少了,可还是60分,没解决根本问题。后来看了阶乘的质因数分解,很神奇!!!

    将这个神奇的东西做一下介绍(引自网络):

    求m!分解质因数后因子n的个数。
    这道题涉及到了大数问题,如果相乘直接求的话会超出数据类型的范围。
    下面给出一种效率比较高的算法,我们一步一步来。
    m!=1*2*3*……*(m-2)*(m-1)*m
    可以表示成所有和n倍数有关的乘积再乘以其他和n没有关系的
    =(n*2n*3n*......*kn)*ohter other是不含n因子的数的乘积因为kn<=m 而k肯定是最大值所以k=m/n
    =n^k*(1*2*......*k)*other 
    =n^k*k!*other
    从这个表达式中可以提取出k个n,然后按照相同的方法循环下去可以求出k!中因子n的个数。
    每次求出n的个数的和就是m!中因子n的总个数。

     

    我的理解:

    1、m!=1*2*3*……*m,里面肯定有n的整数倍,也就是1*2*……n……2*n……3*n……k*n……m;

    2、里面有几个n的倍数就在M!中有几个n,于是m/n个;

    3、可是还有些特殊情况,如n*n,n*n*n,这样在m/n的得数中再除n,再除n,再除n,……知道为0;

     

    关于线性筛法要注意:

    if(i%ss[j]==0)break;

    __________________________________________________________________

     

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int m=5000001;
     8 const int md=100000007;
     9 int n,js=0;
    10 long long ans=1;
    11 long long sz[m],ss[m],cs[m];
    12 void sss()//线性筛法
    13 {
    14     memset(sz,-1,sizeof(sz));
    15    for(int i=2;i<m;i++)
    16    {
    17            if(sz[i])ss[js++]=i;
    18            for(int j=0;j<js&&i*ss[j]<m;j++)
    19            {
    20                sz[i*ss[j]]=0;
    21               if(i%ss[j]==0)break;
    22            }
    23    }
    24 }
    25 void fj(int i)//n的阶乘中含有多少个ss[i],时间复杂度可能是logxn(感觉是)
    26 {
    27     int x=ss[i];
    28     int k=n;
    29     while(k)
    30     {
    31         k=k/x;
    32         cs[i]+=k;
    33     }
    34 }
    35 long long  por(long long x,long long y)//快速幂
    36 {
    37     if(y%2)y=y-1;
    38     x=x%md;
    39     long long anss=1;
    40     long long ds=x;
    41     for(;y>0;y>>=1)
    42     {
    43         if(y&1)anss*=ds;
    44         anss%=md;
    45         ds=(ds%md)*(ds%md)%md;
    46     }
    47     return anss;
    48 }
    49 int main()
    50 {
    51      freopen("hao.in","r",stdin);
    52      freopen("hao.out","w",stdout);
    53     scanf("%d",&n);
    54     sss();
    55     for(int i=0;i<js;i++)
    56     fj(i);
    57     for(int i=0;i<js;i++)
    58     {
    59         ans*=por(ss[i],cs[i]);
    60         ans%=md;
    61     }
    62     cout<<ans; 
    63       fclose(stdout);
    64       fclose(stdin);
    65     return 0;
    66 }
  • 相关阅读:
    由于空间,注定的结果——第五届山东省ACM编程比赛总结
    GPS 偏移校正(WGS-84) 至(GCJ-02) java版本号以实现
    IM设计与实现的系统模块的聊天记录
    Android数据存储——SQLite数据库(模板)
    JAVA多线程和并发基础面试问答
    好博客
    浅谈Java中的equals和==
    JVM的内存区域划分
    try,catch,finally
    Java 如何有效地避免OOM:善于利用软引用和弱引用
  • 原文地址:https://www.cnblogs.com/gryzy/p/6050054.html
Copyright © 2020-2023  润新知