#162 (Div. 2)
A.
B.
C.
题意:从一个递增数字序列中找出一串最长的序列满足任意相邻的数字不互质。
分析:
The main idea is DP. Let's define dp[x] as the maximal value of the length of the good sequence whose last element is x, and define d[i] as the (maximal value of dp[x] where x is divisible by i).
You should calculate dp[x] in the increasing order of x. The value of dp[x] is (maximal value of d[i] where i is a divisor of x) + 1. After you calculate dp[x], for each divisor i of x, you should update d[i] too.
This algorithm works in O(nlogn) because the sum of the number of the divisor from 1 to n is O(nlogn).
Note that there is a corner case. When the set is {1}, you should output 1.
不打质数表
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define clr(x) memset(x,0,sizeof(x)) const int maxn = 100005; int dp[maxn]; int pr[maxn]; int main() { int i, j, k, tp; int n, p, res,r,tmp; while (scanf("%d",&n)!=EOF) { clr(dp); for (i=0; i<n; i++) { scanf("%d",&p); if (i==n-1) r = p; tmp = 0; tp = 0; for (j=2; j*j<=p; j++) { if (p%j==0) { pr[tp++] = j; tmp = tmp>dp[j]?tmp:dp[j]; while (p%j==0) p /= j; } } if (p!=1) { pr[tp++] = p; tmp = tmp>dp[p]?tmp:dp[p]; } tmp++; while (tp--) dp[pr[tp]] = tmp; } res = 0; for (i=0; i<=r; i++) if (dp[i]>res) res = dp[i]; if (res == 0) res++; printf("%d\n",res); } return 0; }
打质数表
#include <cstdio> #include <cstring> #include <cmath> #define clr(x) memset(x,0,sizeof(x)) const int maxn = 100005; int dp[maxn]; int p[maxn]; int main() { int i, j, k; clr(p); for (i=2; i<100001; i++){ if (p[i]==0){ for (j=i; j<100001; j+=i) p[j] = i; } } int res,n, t, x, tmp; while (scanf("%d",&n)!=EOF) { clr(dp); for (i=0; i<n; i++) { scanf("%d",&t); x = t; tmp = 0; while (x>1){ tmp = dp[p[x]]>tmp?dp[p[x]]:tmp; x /= p[x]; } x = t; tmp++; while (x>1){ dp[p[x]] = tmp; x /= p[x]; } } res = 1; for (i=2; i<=100000; ++i) if (dp[i]>res) res = dp[i]; printf("%d\n",res); } return 0; }