反素数小结

 反素数

反素数的定义:对于任何正整数,其约数个数记为,例如,如果某个正整数满足:对任意的正整

 数,都有,那么称为反素数。

从反素数的定义中可以看出两个性质:

(1)一个反素数的所有质因子必然是从2开始的连续若干个质数,因为反素数是保证约数个数为的这个数尽量小

(2)同样的道理,如果,那么必有

其实知不知道反素数这个东西倒是无所谓。关键是理解这两条性质是怎么得出来的。理解了这个,那么相关的题就往这方面想就行了。

这里解释一下这两条性质:定义里的是严格小于,这个很重要,这就决定了一个数如果是反素数,那么它一定是满足条件的最小的数。

那么要找反素数,一定是按着这两条性质来找才能保证是最小的。

例题:

Codeforces#27(div2)E:

http://codeforces.com/problemset/problem/27/E

 题意:给一个正整数n,输出有n个因子的最小的数。

就是按那两条思路来dfs。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define INF 1000000000
#define eps 1e-8
#define pii pair<int,int>
#define LL long long int
#define ULL unsigned long long int
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
/*素数一直连乘,乘到47就不能再往下乘了,否则就超了unsigned long long int了*/
int n;
ULL ans=1000000000000000009;
void dfs(int pi,int num,int limit,ULL temp)
/*pi表示当前用到第几个素数,num表示当前数的因子个数,
limit表示当前用到的这个素数最多能用几次方,temp表示当前数的大小。*/
{
    if(num>n) return;
    else if(num==n)
    {
        ans=min(ans,temp);
        return;
    }
    else
    {
        ULL t=prime[pi];
        for(int i=1;i<=limit;i++,t*=prime[pi])
        {
            dfs(pi+1,num*(i+1),i,temp*t);
        }
    }
}
int main()
{
    //freopen("in6.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%d",&n);
    dfs(0,1,60,1);
    printf("%I64d\n",ans);
    return 0;
}
View Code

 ZOJ 2652 

这道题和上道题一样的,旧瓶装新酒。我之前过了,今天又写了一遍怎么都得不到正确结果,原来是递归函数传参数时改变了原来的值。以前真没有注意到这个易错点。经验值+1。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define INF 1000000000
#define eps 1e-8
#define pii pair<int,int>
#define LL long long int
#define ULL unsigned long long int
LL n,ans,anum;
long long prime[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
/*先用计算器算一下乘到哪个就够了,避免下面不必要的计算。*/
void dfs(LL pi,LL limit,LL num,LL temp)
{
    if(temp>n) return;
    else
    {
        if(num>anum)
        {
            anum=num;
            ans=temp;
        }
        else if(num==anum&&temp<ans)
        {
            ans=temp;
        }
        LL t=(LL)prime[pi];
        for(LL i=1; i<=limit; i++,t*=(LL)prime[pi])
        {
            if(temp*t>n)break;//
            else
                dfs(pi+1,i,num*(i+1),temp*t);
            /*这里犯了一个错误,导致一直WA而找不到bug。
            我把这句写成了dfs(pi+1,i,num*(i+1),temp*=t);
            这个错误非常典型!在递归调用函数时,我要传入temp*t的值,
            但是如果这么写,当前函数的这一层的temp也变了!而此时for循环
            可能还没有结束,temp的值变了肯定会导致错误。
            包括第一个参数就得写成pi+1而不能写成pi++也是一样的道理。*/
            /*这使我认识到了一个重要点:注意递归调用函数传递参数时,不要改变原参数的值!!!*/
        }
    }
}
int main()
{
    //freopen("in7.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(scanf("%I64d",&n)==1)
    {
        ans=1;
        anum=1;
        dfs(0,51,1LL,1LL);
        printf("%I64d\n",ans);
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}
View Code

 

posted @ 2014-08-25 20:13  周洋  阅读(403)  评论(0)    收藏  举报