zoukankan      html  css  js  c++  java
  • Luogu P4310 绝世好题 (dp)

    P4310 绝世好题

    题目大意:

    给出一个数列a,求a的子序列b的最长长度,满足(b_i & b_{i-1} eq 0)

    思路:

    很容易联想到(O(n^2))求最长上升子序列。

    for i in range(1, n + 1):
        dp[i] = 1
        for j in range(1, i):
            if (a[i] & a[j]) != 0:
                dp[i] = max(dp[i], dp[j] + 1)
        ans = max(ans, dp[i])
    

    接下来考虑怎么优化。

    结合按位与的运算法则可以发现只要两个数之间存在一位二进制位上有相同的1就可以让长度加一,即可的到状态转移方程。

    考虑一个样例

    3
    3 6 4
    

    将三个数化为对应的二进制形式即

    011
    110
    100
    

    可以发现“110”中的第一个1的dp值同样为2,这就提醒我们在每次状态转移之后更新dp[i]。

    Code:
    import java.io.*;
    import java.util.*;
    
    public class Main {
        public static final double eps = 1e-6;
        public static final int N = 32;
        public static final int INF = 0x3f3f3f3f;
        public static final int mod = 1000000007; //998244353
    
        public static int[] dp; //dp[i]为当前二进制位为第i位时满足要求的最长长度
        public static int maxx; //当前满足条件的最大长度
        public static int ans;
    
        public static void main(String[] args) throws IOException {
            StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
            st.nextToken();
            int n = (int)st.nval;
            dp = new int[N];
            for (int t = 1; t <= n; t++) {
                st.nextToken();
                int a = (int)st.nval;
                for (int i = 0; i <= 31; i++) {
                    if (((1 << i) & a) != 0) { //由于是求子序列,只要当前数a的第i位二进制数位1,就能使dp[i]+1
                        maxx = Math.max(maxx, dp[i] + 1); //只要相邻两个数之间有一个二进制位上相同的1就可以让长度加一
                    }
                }
                for (int i = 0; i <= 31; i++) {
                    if (((1 << i) & a) != 0) {
                        dp[i] = Math.max(dp[i], maxx); //当前满足条件的二进制为的最大长度都为maxx
                    }
                }
                ans = Math.max(maxx, ans);
            }
            System.out.println(ans);
        }
    }
    
    /*
    3
    3 6 4
    
    5
    5 2 5 2 5
    
    5
    1 5 5 1 1
     */
    
  • 相关阅读:
    敏捷开发原则与实践(一)
    ACM Steps_Chapter Two_Section3
    ACM Steps_Chapter Three_Section3
    ACM Steps_Chapter Three_Section1
    ACM Steps_Chapter Three_Section2
    ACM Steps_Chapter Four_Section1
    java网络编程(2)——UDP与TCP
    java网络编程(1)
    mybatis与spring的整合(使用接口实现crud)
    mybatis与spring的整合(使用sqlSession进行crud)
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14289693.html
Copyright © 2011-2022 走看看