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

转载请注明出处,谢谢 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;
}


评论 1 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

ACM_cxlove

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值