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;
}
原文地址:https://www.cnblogs.com/kkrisen/p/3261628.html