数论 + DP

题意:
给出长度为n(1 <= n <= 1e5)的数列,数列中的数逐渐递增(1 <= ai <= 1e5),问最多能找出长度为多少的序列,满足新序列中相邻的两个数不互素(即gcd(ai, ai+1) > 1 )?
方法:
遍历一遍数组,将当前的数分解质因子,将该数ai的所有质因子存到数组p中。另外,建立数组dp,dp[j]表示质因子j的当前最长序列长度。分解完质因子之后,遍历数组p,更新目前的最长序列长度,用maxn表述长度,则maxn = max(dp[j] + 1, maxn); (这里的dp[j]表示通过因子j与上一个含有因子j的数且长度最长的数相连,则ai可以与该数通过j连在一起,所以dp[j]+1。更新ai的所有质因子,更新最长的长度)。接着,用更新得到的以ai结尾的最长长度,来赋值给ai所含有的所有质因子的最长长度dp[j](以该数结尾的数,最长长度赋值给含有的每个质因子,因为这代表这以这些因子结尾的数最长长度也是那个长度)。最后,遍历所有素数,找到最大长度。
思路好难写,直接上代码吧
 1 //#include<bits/stdc++.h>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <string>
 7 #include <cmath>
 8 #include <cstdlib>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <vector>
13 #include <set>
14 
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> pii;
18 const int INF = 0x7fffffff;
19 const int MAXN = 1e5 + 10;
20 int a[MAXN];
21 int prime[MAXN+1];
22 int p[MAXN];
23 int dp[MAXN];
24 int n;
25 
26 void getPrime() {
27     memset(prime, 0, sizeof(prime));
28     for(int i = 2; i <= MAXN; i++) {
29         if(!prime[i]) prime[++prime[0]] = i;
30         for(int j = 1; j <= prime[0] && prime[j] <= MAXN / i; j++) {
31             prime[prime[j]*i] = 1;
32             if(i % prime[j] == 0) break;
33         }
34     }
35 }
36 
37 void solve() {
38     for(int i = 0; i < n; i++) {
39         int num = a[i], cnt = 0;
40         for(int j = 1; j <= prime[0]; j++) {
41             bool flag = false;
42             while(num % prime[j] == 0) {
43                 flag = true;
44                 num /= prime[j];
45             }
46             if(flag) p[cnt++] = prime[j];
47             if(num == 1) break;
48         }
49         int maxn = 0;
50         for(int j = 0; j < cnt; j++)
51             maxn = max(dp[p[j]] + 1, maxn);
52         for(int j = 0; j < cnt; j++)
53             dp[p[j]] = maxn;
54     }
55     int ans = 1;
56     for(int i = 1; i <= prime[0]; i++)
57         ans = max(ans, dp[prime[i]]);
58     printf("%d\n", ans);
59 }
60 
61 int main(){
62 #ifdef local
63     freopen("case.in", "r", stdin);
64 #endif
65     getPrime();
66 //    for(int i = 1; i <= 10; i++)
67 //        cout << prime[i] << " ";
68 //    cout << endl;
69     scanf("%d", &n);
70     for(int i = 0; i < n; i++)
71         scanf("%d", &a[i]);
72     solve();
73     return 0;
74 }

 

 

posted @ 2018-03-13 23:32  Sissi_hss  阅读(234)  评论(0编辑  收藏  举报