[Codeforces#264B] Good Sequences

Codeforces题号:#264B

出处: Codeforces

主要算法:DP

难度:4.8

思路分析:

  这题DP太难了……

  最终的解法是,令f[i]表示存在因子i的一个数作为子序列结尾的子序列的最大长度。(定义都好难懂啊……)

  现在想一想怎么转移……首先先预处理出对于每一个数a[i]的所有因数。既然相邻的两个数不能是互质的,我们只需要判断相邻两个数的最大公约数是否大于1就好了。

  那么如何判断能否连起来呢?依次枚举a[i],并枚举刚才处理好的a[i]的因数。为什么好枚举因数, 因为所有因数如果在之前的数里出现过,那么当前的a[i]都可以接上去——这一点有点像LIS,选择所有因数中f值最大的去接上去,并且所有因数的f值都可以更新成与其中最大值相同的。因为

代码注意点:

  ……

Code

/** This Program is written by QiXingZhi **/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = 100010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar();
    if(c == ‘-‘) w = -1, c = getchar();
    while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar();
    return x * w;
}
int n,cur,_max,ans;
int a[N],f[N];
vector <int> factor[N];
inline void MadeFactor(int I){
    int x = a[I];
    int lim = floor(sqrt(x));
    factor[I].push_back(x);
    for(int i = 2; i <= lim; ++i){
        if(x % i == 0){
            factor[I].push_back(i);
            if(i!=x/i) factor[I].push_back(x/i);
        }
    }
}
int main(){
//    freopen(".in","r",stdin);
    n = r;
    for(int i = 1; i <= n; ++i){
        a[i] = r;
        MadeFactor(i);
    for(int i = 1; i <= n; ++i){
        _max = 0;
        int sz = factor[i].size();
        for(int j = 0; j < sz; ++j){
            cur = factor[i][j];
            ++f[cur];
            _max = Max(_max, f[cur]);
        }
        for(int j = 0; j < sz; ++j){
            f[factor[i][j]] = _max;
        }
    }
    for(int i = 1; i <= a[n]; ++i){
        ans = Max(ans, f[i]);
    }
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/qixingzhi/p/9310133.html

时间: 2024-10-18 04:51:14

[Codeforces#264B] Good Sequences的相关文章

CodeForces 264B Good Sequences dp

题目链接:点击打开链接 题意: 给定n个数, 构造一个序列(只能选给出的n个数,但数字可重复用) 使得序列严格递增且相邻的两个数字不互质 思路: 因为是严格递增,所以给输入的n个数排个序,相当于选n个数中的子序列了. 把每个数都分解质因数,然后用质因数转移方程即可. import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.math.BigInt

【Codeforces 264B】Good Sequences

[链接] 我是链接,点我呀:) [题意] 让你在一个递增数组中选择一个最长子序列使得gcd(a[i],a[i+1])>1 [题解] 设f[i]表示以一个"含有素因子i的数字"作为序列的结尾的最长序列的长度 显然更新的时候 假设枚举到了a[i] 先求出它所有的素因子p[] 因为要和前面一个数字不互质 那么只能找结尾数字有这些素因子p[]的数字 因此我们求出f[p[1~cnt]]中的最大值Ma,他们最大值对应的序列再加上一个a[i]的话 长度就变成Ma+1了 然后f[p[1~cnt]

CodeForces 373B Making Sequences is Fun

Making Sequences is Fun Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 373B Description We'll define S(n) for positive integer n as follows: the number of the n's digits in the decimal

Codeforces 900D Unusual Sequences 容斥原理

题目链接:900D  Unusual Sequences 题意: 给出两个数N,M.让你求数列(和为M,gcd为N)的个数. 题解: 首先,比较容易发现的是M%N如果不为零,那么一定不能构成这样的序列.那么可以设 k = M/N,则可以想象为用k个1来构成序列的个数,运用隔板原理可以求出k个1可以构成的序列总数为2^(k-1),但是这里面其实有不构成条件的(gcd>N)比方说6个相同的数(2,2,2)构成这样gcd就是2×N而不是N了.所以要减去这些数的情况,这样减的话发现不能用递归来做,要先记

Codeforces Jzzhu and Sequences(循环节)

# include <stdio.h> int f[10]; int main() { int x,y,n,j; while(~scanf("%d%d%d",&x,&y,&n)) { f[1]=x; f[2]=y; for(j=3;j<=6;j++) { f[j]=f[j-1]-f[j-2]; } n%=6; if(n==0) n=6; if(f[n]>=0) printf("%d\n",f[n]%1000000007

【矩阵快速幂 】Codeforces 450B - Jzzhu and Sequences (公式转化)

[题目链接]click here~~ [题目大意] Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn modulo1000000007(109?+?7). [解题思路] /*A - Jzzhu and Sequences Codeforces 450B - Jzzhu and Sequences ( 矩阵快速幂 )

Codeforces Round #FF(255) C. DZY Loves Sequences (LIS升级)

题目:C. DZY Loves Sequences (LIS升级) 题意: 在n个数中,最多改变一个数字,并求能够达到的最长严格上升子序列(连续)长度 分析: 考虑第i个数,能否改变后拼接前后两个字串,并维护当前最大值 状态: left[i]:  表示以i为终点的最长严格上升子序列长度 right[i]: 表示以i为起点的最长严格上升子序列长度 dp[i]:   表示改变第i个数后,拼接前后字串的长度 转移方程:       dp[i] = max{left[i-1] + right[i+1] 

Codeforces Round #243 (Div. 1)——Sereja and Two Sequences

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

[2016-04-13][codeforces][447][C][DZY Loves Sequences]

时间:2016-04-13 23:39:47 星期三 题目编号:[2016-04-13][codeforces][447][C][DZY Loves Sequences] 题目大意:给定一串数字,问改变其中一个数字之和,最长能得到多长的严格增加的子串 分析: 维护每个数字往左和往右能延续多长(严格减,增),然后枚举每个点, 如果这个点已经在一个严格增加的序列中,那么ans =min(n, max(ans , l[i] + r[i] + 1)) 即左右两边延伸之后,改变后面非递增的一个数字 注意这