概述
题目:给出K个数,p1,p2,……pk,不一定是素数,给这些数添加指数,0-10之间,最终的乘积为n,他的所有因子和为m,问是否存在一个m为2的幂,如果有多个输出最大的指数,如果没有输出NO。
思路:
如果p是一个素数,并且m=2^p-1也是素数,那么m就称为梅森素数
一个重要的定理:“一个数能够写成几个不重复的梅森素数的乘积” 等价于 “这个数的约数和是2的幂次”。N的约数和的2的幂次是可以直接由构成它的梅森素数的来源的2的幂次p相加而得到。
在题目给出的范围之内,只有8个梅森素数。状态压缩dp解决
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
const int maxn=150;
int p[maxn],sta[maxn],dp[1<<8];
int mason[8]={3,7,31,127,8191,131071,524287,2147483647};
int cnt[8]={2,3,5,7,13,17,19,31};
int judge(int n){
int res=0;
for(int i=0;i<8;i++){
if(n%mason[i]==0){
n/=mason[i];
res|=(1<<i);
if(n%mason[i]==0)
return 0;
}
}
if(n>1) return 0;
return res;
}
int cal(int sta){
int res=0;
for(int i=0;i<8;i++)
if((sta&(1<<i)))
res+=cnt[i];
return res;
}
int main(){
int N,n;
while(~scanf("%d",&N)){
n=0;
for(int i=0;i<N;i++){
scanf("%d",&p[i]);
sta[n]=judge(p[i]);
if(sta[n]!=0)
n++;
}
if(n==0){
printf("NOn");
continue;
}
mm(dp,0);
dp[0]=1;
for(int i=0;i<n;i++)
for(int j=0;j<(1<<8);j++)
if((j&sta[i])==0)
dp[j|sta[i]]|=dp[j];
int ans=0;
for(int i=0;i<(1<<8);i++)
if(dp[i])
ans=max(ans,cal(i));
printf("%dn",ans);
}
return 0;
}
最后
以上就是精明百褶裙为你收集整理的POJ - 1777 Vivian's Problem 梅森素数+状压dp的全部内容,希望文章能够帮你解决POJ - 1777 Vivian's Problem 梅森素数+状压dp所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复