bjoi 2010 取数游戏 动态规划

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

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

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

 1 #include<iostream>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 #define MAXN 50001
 7 int n,m,top,factor_num;
 8 int a[MAXN];
 9 int factor[1000],prime[1000],p[1000],p_num[1000];
10 int num[1000001];
11 bool use[1001];
12 void find_prime()
13 {
14     int i,j;
15     memset(use,1,sizeof(use));
16     for(i=2;i<=1000;i++)
17     if(use[i])
18         for(j=i*i;j<=1000;j+=i)
19             use[j]=0;
20     j=0;
21     for(i=2;i<=1000;i++)
22         if(use[i])
23             prime[++j]=i;
24     prime[++j]=987654321;
25 }
26 void div(int x)
27 {
28     top=0;
29     for(int i=1;prime[i]<=sqrt(x);i++)
30     {
31         if(x%prime[i]==0)
32         {
33             p[++top]=prime[i];
34             p_num[top]=0;
35         }
36         while(x%prime[i]==0)
37             p_num[top]++,x=x/prime[i];
38     }
39     if(x!=1)
40     {
41         p[++top]=x;
42         p_num[top]=1;
43     }
44 }
45 void dfs(int i,int x)
46 {
47     if(i==top+1)
48     {
49         factor[++factor_num]=x;
50         return ;
51     }
52     dfs(i+1,x);
53     for(int j=0;j<p_num[i];j++)
54     {
55         x=x*p[i];
56         dfs(i+1,x);
57     }
58 }
59 int find_answer()
60 {
61     int s=0;
62     for(int i=1;i<=factor_num;i++)
63         if(factor[i]>=m&&num[factor[i]]>s) s=num[factor[i]];
64     for(int i=1;i<=factor_num;i++)
65         if(factor[i]>=m) num[factor[i]]=s+1;
66     return s+1;
67 }
68 int solve()
69 {
70     int s=0,i,j,t;
71     for(i=1;i<=n;i++)
72     {
73         div(a[i]);
74         factor_num=0;
75         dfs(1,1);
76         t=find_answer();
77         if(t>s) s=t;
78     }
79     return s;
80 }
81 int main()
82 {
83     memset(num,0,sizeof(num));
84     find_prime();
85     scanf("%d%d",&n,&m);
86     int i;
87     for(i=1;i<=n;i++) scanf("%d",a+i);
88     printf("%d",solve());
89     return 0;
90 }
原文地址:https://www.cnblogs.com/myoi/p/2481313.html