您的位置:首页 > 其它

bjoi 2010 取数游戏 动态规划

2012-05-03 21:07 162 查看
题意:小 C 刚学了辗转相除法,正不亦乐乎,这小 P 又出来捣乱,给小 C 留了个 难题。 给 N 个数,用 a1,a2…an来表示。现在小 P 让小 C 依次取数,第一个数可以 随意取。假使目前取得 aj,下一个数取ak(k>j),则ak必须满足gcd(aj,ak)≥L。 到底要取多少个数呢?自然是越多越好! 不用多说,这不仅是给小 C 的难题,也是给你的难题。

思路:类似最长上升子序列

建一个num[1000000]数组 表示当前是x的倍数的数最多能取num[x]个

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 50001
int n,m,top,factor_num;
int a[MAXN];
int factor[1000],prime[1000],p[1000],p_num[1000];
int num[1000001];
bool use[1001];
void find_prime()
{
int i,j;
memset(use,1,sizeof(use));
for(i=2;i<=1000;i++)
if(use[i])
for(j=i*i;j<=1000;j+=i)
use[j]=0;
j=0;
for(i=2;i<=1000;i++)
if(use[i])
prime[++j]=i;
prime[++j]=987654321;
}
void div(int x)
{
top=0;
for(int i=1;prime[i]<=sqrt(x);i++)
{
if(x%prime[i]==0)
{
p[++top]=prime[i];
p_num[top]=0;
}
while(x%prime[i]==0)
p_num[top]++,x=x/prime[i];
}
if(x!=1)
{
p[++top]=x;
p_num[top]=1;
}
}
void dfs(int i,int x)
{
if(i==top+1)
{
factor[++factor_num]=x;
return ;
}
dfs(i+1,x);
for(int j=0;j<p_num[i];j++)
{
x=x*p[i];
dfs(i+1,x);
}
}
int find_answer()
{
int s=0;
for(int i=1;i<=factor_num;i++)
if(factor[i]>=m&&num[factor[i]]>s) s=num[factor[i]];
for(int i=1;i<=factor_num;i++)
if(factor[i]>=m) num[factor[i]]=s+1;
return s+1;
}
int solve()
{
int s=0,i,j,t;
for(i=1;i<=n;i++)
{
div(a[i]);
factor_num=0;
dfs(1,1);
t=find_answer();
if(t>s) s=t;
}
return s;
}
int main()
{
memset(num,0,sizeof(num));
find_prime();
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++) scanf("%d",a+i);
printf("%d",solve());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: