题意:求最长严格上升子序列,并保证该子序列相邻不互质(数据范围:元素个数10^5,元素大小10^5)
题目突破点每个数组元素大小不超过10^5,预先将所有数分解质因数O(N*|prime|),或者筛出所有数的因子O(N*lgN)。
dp[num[i]]=max(dp[num[i]的因子]+1) (dp[i]为以i为结尾的最长子序列长度)
后来瞻仰了CLJ神牛的代码,STL用的很神,就顺手剽窃过来了……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <list> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <bitset> 14 #include <algorithm> 15 #include <numeric> 16 #include <functional> 17 using namespace std; 18 typedef long long ll; 19 #define inf (int)1e10 20 #define exp 1e-8 21 #define read freopen("in.txt","r",stdin) 22 #define write freopen("out.txt","w",stdout) 23 #define maxn 100005 24 vector<int>dx[maxn]; 25 int dp[maxn]; 26 void init()//筛因子O(N*lgN) 27 { 28 for(int i=2;i<maxn;i++) 29 for(int j=i;j<maxn;j+=i) 30 dx[j].push_back(i); 31 } 32 int main() 33 { 34 //read; 35 init(); 36 int n,num; 37 while(~scanf("%d",&n)) 38 { 39 memset(dp,0,sizeof(dp)); 40 for(int i=0;i<n;i++) 41 { 42 scanf("%d",&num); 43 int t=1; 44 for(vector<int>::iterator e=dx[num].begin();e!=dx[num].end();e++)//求当前num的最大上升不互质数列长度 45 t=max(t,dp[*e]+1); 46 for(vector<int>::iterator e=dx[num].begin();e!=dx[num].end();e++)//用t更新num的因子dp值 47 dp[*e]=max(dp[*e],t); 48 } 49 int ans=1; 50 for(int i=0;i<maxn;i++) 51 ans=max(ans,dp[i]); 52 printf("%d\n",ans); 53 } 54 return 0; 55 }