http://poj.org/problem id=1777
这里需要用到一种特殊的素数:梅森素数
我们把满足 E = 2 ^ i - 1 的素数E称作梅森素数。
关于梅森素数,有一个重要的定理:“一个数能够写成几个不重复的梅森素数的乘积” 等价于 “这个数的约数和是2的幂次”,但是不能重复,比如说3是梅森素数,9就不满足约数和为2的幂。
还有一个重要内容就是,N的约数和幂次是可以直接由构成它的梅森素数的来源幂次相加而得的。
梅森素数是非常少的,在题目给出的范围之内,只有8个梅森素数,可以打表列出,然后判断每一个给出的数中是不是唯一拥有若干个梅森素数。对于某个梅森素数因子,必须只有一个因子,因为之前说过了,对于9.3*3他便 不满足,而且如果有别的因子肯定也不满足。
之后由于只有8个梅森素数,使用状态压缩DP即可。
[cpp]
#include
#include
#include
#include
#include
#include
#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< }
}
//如果还有别的因子,返回0
if(num!=1) return 0;
return ret;
}
int sum=0;
for(int i=0;i<8;i++)
if(state&(1< sum+=cnt[i];
return sum;
}
int main(){
int n,a[100];
while(scanf("%d",&n)!=EOF){
for(int i=0;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
if(!(j&a[i]))
dp[j|a[i]]|=dp[j];
}
int ans=0;
for(int i=0;i<(1<<8);i++)
if(dp[i]) www.2cto.com
ans=max(ans,clac(i));
printf("%d\n",ans);
}
return 0;
}
作者:ACM_cxlove