POJ - 1777Vivian's Problem梅森素数+状压dp

xiaoxiao2021-02-28  144

题目:给出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("NO\n"); 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("%d\n",ans); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-17438.html

最新回复(0)