Vivian’s Problem
Time Limit: 1000MS
Memory Limit: 30000K
[显示标签]
Description
The desire to explore the unknown has been a driving force in human history since the dawn of time. From the earliest documented accounts, ancient civilizations had explored the earth by sailing around. Early adventurers were motivated by religious beliefs, the desire conquest, the need to establish trade routes, and hunger for gold.
You never know what will happen before the exploration. Neither does Bruce Lee. Someday, Mr.Lee entered a desolate tropical rainforest. And after several days’ exploring, he came in front of a cave with something blinking in it. A beautiful girl named Vivian came out just before he tried to go into the cave. And Vivian told Mr. Lee that he must answer some questions before he entered the cave. As the best friend of Mr. Lee, you should help him to work it out.
You will get k positive integers p1, p2 … pi … pk (1 <= i <= k) from Vivian. From these numbers, you can calculate N, N=Π1<=i<=kpiei (0 <= ei <= 10, Σ1<=i<=kei>=1, 1 <= i <= k); you may decide the integers eis as you wish. From one N, you can calculate corresponding M, which equals to the sum of all divisors of N. Now, you should tell Vivian whether or not there is an M which is the power of 2 (1,2, 4, 8, and 16 … so on). If there’s no N can make M equal to the power of 2, tell Vivian “NO”. If M equals to some 2x, then show her the exponent (x). And if there are several x, only show her the largest one.
Input
Input contains several testcases. For each testcase, the first line contains only one integer k (0 < k <= 100), representing the number of positive integers. Then there are k positive integers p1, p2 … pi … pk (1 < pi < 231, 1 <= i <= k) in the second line, representing the given numbers.
Input is terminated by end of file.
Output
For each testcase, you should output your result in a single line. If you can find N from the given numbers, output the largest exponent. Otherwise, output “NO”. Extra spaces are not allowed.
Sample Input
1
2
3
2 3 4
Sample Output
NO
2
题意:给100个int以内的数,每个数可以选0-10次乘到M里,加起来必须至少选1次,初始M=1。要使得M的约数和N是2的整数次幂,并输出最大幂次。
做法:将M分解质因数,举例说明N的计算方法:
M=2^3x5x7^4
约数和N为:(1+2+4+8)x(1+5)x(1+7+7^2+7^3+7^4)
然后发现形如2^p-1的不同素数的乘积的N是2的整数幂,这种素数称为梅森素数。
范围内共有梅森素数8个,状压dp即可。
关键是要知道结论吧。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
ll ans;
bool judge[100000];
ll prime[50000];
ll mason[20];
ll masont[20];
ll totprime;
ll totmason;
bool dp[105][300];
int k;
bool isprime(ll num)
{
for(int i=2;prime[i]*prime[i]<=num;i++)
if(num%prime[i]==0)return false;
return true;
}
bool cal(ll num, ll &pos)
{
pos=0;
for(int i=1;i<=8;i++)
{
if(num%mason[i])continue;
else{
num/=mason[i];
if(num%mason[i]==0)return false;
pos|=(1<<(i-1));
}
}
if(num>1)return false;
return true;
}
bool pipei(ll tar, ll par, ll tur)
{
if(dp[tur-1][tar])return true;
else{
ll lef=0;
for(int i=1;i<=8;i++)
{
if(tar&(1<<(i-1))&&!(par&(1<<(i-1))))lef|=(1<<(i-1));
else if(!(tar&(1<<(i-1)))&&par&(1<<(i-1)))return false;
}
return dp[tur-1][lef];
}
}
ll cost(ll pos)
{
ll ans=0;
for(int i=1;i<=8;i++)
if(pos&(1<<(i-1)))ans+=masont[i];
return ans;
}
int main()
{
memset(judge, true, sizeof(judge));
totprime=0;
for(int i=2;i<100000;i++)
{
if(judge[i])
{
prime[++totprime]=i;
for(int j=2;j*i<100000;j++)judge[i*j]=false;
}
}
totmason=0;
for(int i=2;i<=31;i++)
{
if(prime[i]&&isprime((1LL<<i)-1))
{
mason[++totmason]=(1LL<<i)-1;
masont[totmason]=i;
}
}
//printf("%lld\n",totmason);
while(~scanf("%d", &k))
{
memset(dp, false, sizeof(dp));
dp[0][0]=true;
ll tmp;
for(int i=1;i<=k;i++)
{
scanf("%lld", &tmp);
ll pos=0;
if(!cal(tmp, pos))
{
for(int j=0;j<(1<<8);j++)
dp[i][j]=dp[i-1][j];
}
else{
for(int j=0;j<(1<<8);j++)
dp[i][j]=pipei(j, pos, i);
}
}
ll ans=0;
for(int j=0;j<(1<<8);j++)
{
if(dp[k][j])ans=max(ans, cost(j));
}
if(ans)printf("%lld\n", ans);
else printf("NO\n");
}
}
本文解析了一道算法竞赛题目 Vivian's Problem,题目要求从给定的若干正整数中选择一些数的幂次组合成新的数 N,使得 N 的所有因数之和 M 是2的幂次。文章提供了详细的解题思路与代码实现。
2676

被折叠的 条评论
为什么被折叠?



