题意:小 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 }