题目:http://codeforces.com/problemset/problem/264/B
题意:给你一串递增序列,找出最长的一段子序列,满足两两相邻的两个数不互质,并求出最长的子序列长度;
思路:官方题解上说是个DP,但我觉得我的做法好像不是DP。。就hash了一下每个数的因子;比赛的时候,算错了复杂度,直接套了个O(n^2)求最长上升子序列的上去,还过了样例,不过最后被hack了。。这题比赛时能做对的,但是被hack的时候剩下时间也不多了,所以也就没什么时间去做了;我的做法是开一个长度为n的vector,然后把第i个数的因数都存进第i个vector中;再开一个数组dp[因子]存储当前以因子x为终点最长的子序列长度,然后再从头开始遍历,将第i个数的所有因子dp[因子]++,然后再求出第i个数的因子中数目最大的那个,记为Max,然后更新,
dp[第i个数的所有因子 = Max;答案就是res = max(dp[i])1<= i <=num[n] ,其实是出现过的所有因子,看下样例找规律也挺好找的;
#include<cstdio>
#include<vector>
#include<math.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define PB push_back
using namespace std;
const int N = 100010;
const int M = 510;
const int MININF = -10000000;
int num[N], dp[N];
vector<int> V[N];
void getDiv(int x,int idx){
if(x == 1){
V[idx].PB(1);
return ;
}
int len = (int)sqrt(x);
for(int i = 2;i <= (int)len;i++)
if(x % i == 0)
V[idx].PB(i), V[idx].PB(x / i);
if(len * len == x)
V[idx].pop_back();
V[idx].PB(x);
}
int main(){
int i, j, n;
scanf("%d", &n);
for(i = 1;i <= n;i++){
scanf("%d", &num[i]);
getDiv(num[i], i);
}
memset(dp, 0, sizeof(dp));
for(i = 1;i <= n;i++){
int Max = MININF;
for(j = 0;j < (int)V[i].size();j++){
dp[V[i][j]]++;
Max = max(Max, dp[V[i][j]]);
}
for(j = 0;j < (int)V[i].size();j++)
dp[V[i][j]] = Max;
}
int res = MININF;
for(i = 1;i <= num[n];i++)
res = max(res, dp[i]);
cout<< res << endl;
return 0;
}