zoukankan      html  css  js  c++  java
  • 18省夏day1

    1、素因数分解

           1、https://www.luogu.org/problemnew/show/P1075

           2、https://www.luogu.org/problemnew/show/CF776B:这道题显然可以将素数化为                         1,合数变为2,然后因为长度到了100000,所以应使用埃氏筛法。但实践是一直有问题,1、要注意i等于1和2的特例;2、

           3、整数惟一分解定理:任意一个大于0的正整数都能被表示成若干个素数的乘积且表示方法是唯一的;整理可以将相同素数的合并;可以得到公式————n = P1^a1 * P2^a2 * …………*Pn^an (P1 < P2 < ……Pn);有一些小细节要注意

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int n;
    int a[10000];
    int p[10000]; 
    int main(){
        scanf("%d",&n);
        int m=n;//注意应用m代替n,不用中途会变小 
        int count=0;
        for(int i=2;i*i<=n;i++){
            while(m%i==0){//因为一定会把带有这个素数的除完,所以肯定不会被合数除 
                p[i]++;    //这样写好写方便 
                m/=i;
            }
        }
        if(m>1)p[m]++;//重点!!最后可能会多一个出来,要把本身也算 
        for(int i=2;i<=n;i++)
            if(p[i])
                printf("%d^%d
    ",i,p[i]);
    }
    View Code

     2、素数筛法

           1、埃氏筛法 埃氏筛法的中心还是很好理解,只是要注意从j=i*i开始,降低时间消耗

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int n,a[1001001];
    int main(){
        scanf("%d",&n);
        a[0]=a[1]=1;//将0和1特判,素数 为0
        for(int i=2;i*i<=n;i++){
            if(!a[i]){
                for(int j=i*i;j<=n;j+=i)
                    a[i]=1;
            }
        } 
        for(int i=2;i<=n;i++){
            printf("%d ",a[i]);
        }
        return 0;
    } 
    View Code 

           2、Prime Distance:https://www.luogu.org/problemnew/show/UVA10140   这道题还是应用埃氏筛法,但是这道题显然数据太大,不能筛完全部素数,所以我们可以考虑先筛出2到根号r的所有素数(为了节省时间,要先做,直接到100000>根号的2^31-1),然后注意到l和r间的的范围是有限的,只有1000000,所以就用已算出的素数将其筛掉,即标记i*p-l 为合数(减去l是精华!,然后再用prime2将l到r的素数记录下来即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    int prime1[100100];
    long long prime2[100100];//注意大小,要用ll 
    bool check[1000100];//用bool占用的空间较小 
    int count1=1,count2;
    int main(){//往往错在最没想到会错的地方 
        for(int i=2;i*i<=100100;i++)
            if(!check[i]){//写错 
                prime1[count1++]=i;
                for(long long j=i*i;j<=100100;j+=i)//j应+=i 
                    check[j]=1;//写错 
            }    
    /*    for(int i=1;i<=10;i++)
            cout<<prime1[i]<<"   ";*/
        long long L,R;    
        long long mina,maxa,x1,x2,y1,y2;
        while(scanf("%lld%lld",&L,&R)!=EOF){
            mina=131313133,maxa=-1;
            x1=x2=y1=y2=0;
            memset(check,0,sizeof(check));
            count2=0;
            L=max(L,(long long)2);//要注意1是特例 
            for(long long i=1;prime1[i]*prime1[i]<=R&&i<count1;i++){//注意在prime1中素数只有count1个 
                long long s=L/prime1[i]+(L%prime1[i]>0);//括号位置!因为范围在L,R间l/prime向下取整,除非正好相等否则要加1 
                if(s==1)s=2;//因为prime本身是素数,如果*1也还是素数,如果从1开始就会把素数判成合数 
                for(long long j=s;j*prime1[i]<=R;j++)//j*prime[i]只有小于r才有意义 
                    check[j*prime1[i]-L]=1;
            }
        /*    for(int i=0;i<335;i++)
                printf("%d  ",check[i]);*/
            for(long long i=0;i<=R-L;i++)//重点,i的取值范围,l可能正好是素数,最多到R-l 
                if(!check[i])prime2[count2++]=i+L;//count2记区间有几个素数 
        /*    for(int i=0;i<count2;i++)
                printf("%d  ",prime2[i]);*/
            for(int i=1;i<count2;i++){
                if(prime2[i]-prime2[i-1]<mina){
                    mina=prime2[i]-prime2[i-1];
                    x1=prime2[i-1],y1=prime2[i];
                }
                if(prime2[i]-prime2[i-1]>maxa){
                    maxa=prime2[i]-prime2[i-1];
                    x2=prime2[i-1],y2=prime2[i];
                }
            }
            if(count2<2)
                printf("There are no adjacent primes.
    ");
            else{
                printf("%lld,%lld are closest, %lld,%lld are most distant.
    ",x1,y1,x2,y2);
            }
        }
        return 0;                
    }
    View Code

          3.利用埃氏筛法优化质因数分解,只要找到在判素数时同时找到最小素因数即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    int prime[1001000],minf[1001000];//确定最小质因数 
    vector<int > ret;
    //做确定素数时要考虑取值范围,是否要用long long来定义 
    void erato(int n){
        prime[0]=prime[1]=0;
        minf[0]=0;minf[1]=1;//特例 
        for(int i=2;i<=n;i++)
            prime[i]=1,minf[i]=i;//当他本身是最小的要么是素数,要么还没找到 
        for(int i=2;i*i<=n;i++)
            if(prime[i]){
                for(int j=i*i;j<=n;j+=i){
                    prime[j]=0;
                    if(minf[j]=j)
                        minf[j]=i;
                }
            }
    }
    int found(int x){
        while(x>1){
            ret.push_back(minf[x]);
            x/=minf[x];
        }
    }
    int main(){
        int n;
        scanf("%d",&n);
        erato(n);
        found(n);
        return 0; 
    }
    View Code

          4.阶乘分解:将阶乘n!(1<=n<=10^6)分解素因数,以唯一分解形式给出pi和ri                朴素想法将1~n质因数分解,再将相同的pi累加,但是这样显然过不了

    然后我们考虑,其实在1~n中,素数也就那几个,所以先找出全部的素数,然后对于每个素数,,N/p^k向下取整就是p出现的个数(通过举例可验证或,因为在n内,对于p的倍数有n/p个,如果有的是p^2的倍数,那么也出现n/p^2个,同理可证)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int n,prime[10010],cs[10010],f[1010010];
    int cnt=1;
    void foun(){
        for(int i=2;i<=n;i++){
            if(!f[i]){
                prime[cnt]=i;cnt++;
                for(int j=i*i;j<=n;j+=i)
                    f[j]=1;
            }
        }
        cnt--;
    }
    void jl(){
        for(int i=1;i<=cnt;i++){
            for(int j=prime[i];j<=n;j*=prime[i])
                cs[i]+=n/j;
        }
    }
    int main(){
        scanf("%d",&n);
        foun();//先找出一到n中所有存在的质数 
        jl();//找每个素数被用的次数 
        for(int i=1;i<cnt;i++)
            printf("%d^%d+",prime[i],cs[i]);
        printf("%d^%d",prime[cnt],cs[cnt]);
    }
    View Code

          5.欧拉筛法(线性筛):利用 i 和素数表中的素数 prime[j] 去筛除 i*prime[j] ,为了确保i*prime[j] 只被素数 prime[j] 筛除过这一次,要确保 prime[j] 是i*prime[j] 中最小的素因子,即 i 中不能有比 prime[j] 还要小的素因子

    //线性筛法
    void Euler(){
        for(int i=2;i<=n;i++){
            if(!isprime[i])prime[++prime[0]]=i;
            else{
                for(int j=1;j<=prime[0]&&prime[j]*i<=n;j++){//每次用已确定的素数来筛 
                    isprime[prime[j]*i]=1;
                    if(i%prime[j]==0)break;//这句话是线性筛精华所在,保证每个数只被
                    //它最小的素因子筛去; 
                }
            }
        }
    } 
    View Code
  • 相关阅读:
    ABAP接口用法
    监听textarea数值变化
    The first step in solving any problem is recognizing there is one.
    Wrinkles should merely indicate where smiles have been.
    God made relatives.Thank God we can choose our friends.
    Home is where your heart is
    ABAP跳转屏幕
    Python 工具包 werkzeug 初探
    atom通过remote ftp同步本地文件到远程主机的方法
    Mongodb学习笔记一
  • 原文地址:https://www.cnblogs.com/linzeli/p/9291984.html
Copyright © 2011-2022 走看看