概述
转载请注明出处,谢谢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("%dn",ans);
}
return 0;
}
最后
以上就是能干日记本为你收集整理的POJ 1777 Vivian's Problem(梅森素数)的全部内容,希望文章能够帮你解决POJ 1777 Vivian's Problem(梅森素数)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复