您的位置:首页 > 其它

POJ 1777 Vivian's Problem(梅森素数)

2012-08-13 16:21 218 查看
转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents
by---cxlove

题目:给出K个数,p1,p2,……pk,不一定是素数,给这些数添加指数,0-10之间,最终的乘积为n,他的所有因子和为m,问是否存在一个m为2的幂,如果有多个输出最大的指数,如果没有输出NO。

http://poj.org/problem?id=1777

这里需要用到一种特殊的素数:梅森素数

我们把满足 E = 2 ^ i - 1 的素数E称作梅森素数。

关于梅森素数,有一个重要的定理:“一个数能够写成几个不重复的梅森素数的乘积” 等价于 “这个数的约数和是2的幂次”,但是不能重复,比如说3是梅森素数,9就不满足约数和为2的幂。

还有一个重要内容就是,N的约数和幂次是可以直接由构成它的梅森素数的来源幂次相加而得的。

梅森素数是非常少的,在题目给出的范围之内,只有8个梅森素数,可以打表列出,然后判断每一个给出的数中是不是唯一拥有若干个梅森素数。对于某个梅森素数因子,必须只有一个因子,因为之前说过了,对于9.3*3他便 不满足,而且如果有别的因子肯定也不满足。

之后由于只有8个梅森素数,使用状态压缩DP即可。

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 30
#define inf 1<<29
#define MOD 2007
#define LL long long
using namespace std;
int mason[8]={3,7,31,127,8191,131071,524287,2147483647};
int cnt[8]={2,3,5,7,13,17,19,31};
int dp[1<<8];
int change(int num){
    int ret=0;
    for(int i=0;i<8;i++){
        if(num%mason[i]==0){
            num/=mason[i];
            //这个因子含有多个,返回0
            if(num%mason[i]==0)  return 0;
            ret|=1<<i;
        }
    }
    //如果还有别的因子,返回0
    if(num!=1)  return 0;
    return ret;
}
int clac(int state){
    int sum=0;
    for(int i=0;i<8;i++)
        if(state&(1<<i))
           sum+=cnt[i];
    return sum;
}
int main(){
    int n,a[100];
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            a[i]=change(a[i]);
            if(!a[i])  i--,n--;
        }
        //没有因子满足条件
        if(n==0){
            puts("NO");
            continue;
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<(1<<8);j++)
                if(!(j&a[i]))
                    dp[j|a[i]]|=dp[j];
        }
        int ans=0;
        for(int i=0;i<(1<<8);i++)
            if(dp[i])
                ans=max(ans,clac(i));
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: