• ZOJ- 2562 反素数使用


    借用了下东北师大ACM的反素数模版。

    本来我是在刷线段树的,有一题碰到了反素数,所以学了一下。。有反素数的存在,使得一个x ,使得x的约数个数,在1 到 x的所有数里面,是最大的。

    这里面还涉及安叔那天讲的求一个数的约数个数,用其素数因子的指数相乘即可。

    这是东北师大的模版:

    View Code 
     typedef __int64 INT;
     INT bestNum;   //约数最多的数
     INT bestSum;   //约数最多的数的约数个数
     const int M=1000; //反素数的个数 
     INT n=500000;//求n以内的所有的反素数
     INT rprim[M][2];
     //2*3*5*7*11*13*17>n,所以只需考虑到17即可
     INT prim[14]={2,3,5,7,11,13,17,19,23,29};  
     
     //当前走到num这个数,接着用第k个素数,num的约数个数为sum,
     //第k个素数的个数上限为limit
     void getNum(INT num,INT k,INT sum,INT limit)  {
          if(num>n)return;
         if(sum>bestSum){
             bestSum = sum;
             bestNum = num;
         }else if(sum == bestSum && num < bestNum){  //约数个数一样时,取小数
             bestNum = num;
         }
         if(k>=7) return; //只需考虑到素数17,即prim[6]
       
         for(INT i=1,p=1;i<=limit;i++){   //素数k取i个
             p*=prim[k];
    if(p>n||p*num>n) return; //这里也要判断一下,否则老是爆掉。 getNum(num
    *p,k+1,sum*(i+1),i); } } INT log2(INT n){ //求大于等于log2(n)的最小整数 INT i = 0; INT p = 1; while(p<n){ p*=2; i++; } return i; } int getrprim(){//反素数的个数 int i = 0; while(n>0){ bestNum = 1; bestSum = 1; getNum(1,0,1,log2(n)); n = bestNum - 1; rprim[i][0]=bestNum; rprim[i][1]=bestSum; i++; } return i; }

    ZOJ 2562的代码

    #include <iostream>
    #include <cstdio>
    typedef long long ll;
    using namespace std;
    ll prime[30]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
    ll antinum;
    ll antisum;
    ll antiprime[101][2];
    ll maxn;
    ll log2(ll n)
    {
        ll i=0,p=1;
        while (p<n)
        {
            p*=2;
            i++;
        }
        return i;
    }
    void getanti(ll num,ll sum,ll k,ll limit)
    {
    
        if (num > maxn) return;
        //cout<<num<<endl;
        if (sum>antisum) {antisum=sum;antinum=num;}
        else
         if (sum==antisum&&num<antinum) antinum=num;
        if (k>15) return;
        for (ll i=1,p=1;i<=limit;i++)
        {
            p*=prime[k];
            if (p>maxn||num*p>maxn) return;
            getanti(num*p,sum*(i+1),k+1,i);
        }
    }
    void getnum()
    {
        antinum=1;
        antisum=1;
            //cout<<maxn<<endl;
        getanti(1,1,0,50);
    
    }
    int main()
    {
        //printf("%I64d
    ",maxn);
       // ll cur=getnum();
        ll t;
        //cout<<cur<<endl;
    //    for (int i=cur-1;i>=0;i--)
         //cout<<antiprime[i][0]<<endl;
        while (scanf("%lld",&t)!=EOF)
        {
           maxn=t;
           getnum();
           printf("%lld
    ",antinum);
        }
        return 0;
    }
  • 相关阅读:
    用两个栈实现队列(剑指09题)
    PHP 视频源文件加密方案
    PHP 实现大文件视频推流
    logstash笔记
    yum本地包的获取与安装
    IF.SVNAdmin安装 | SVN权限可视化管理
    Windows全局程序调用 Win + R
    Jenkins复制流水线命令行
    SVN hooks编写[Linux&Windows]
    AA压限, 语音识别去除语气词, 等
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3261628.html
Copyright © 2020-2023  润新知