1498. 满足条件的子序列数目

本文介绍了一种统计满足特定条件的子序列数量的算法。该算法通过枚举最小元素,利用二分查找和快速幂计算满足条件的子序列数量,并使用取模运算防止溢出。适用于解决整数数组中子序列的统计问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1498. 满足条件的子序列数目

给你一个整数数组 nums 和一个整数 target 。
请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。
由于答案可能很大,请将结果对 10^9 + 7 取余后返回。

1.枚举法
vmin<=vmax<=target-vmin
vmin2<=target
枚举vmin,固定vmin,vmax为vmin到【target-vmin】,对剩余元素做二分查找,找到vmax个数,由于vmin
2<=target,每个vmin贡献2^(x-1)
可以先预处理出所有 2^i ( mod( 10 ^9)
+7) 的值,然后对原序列进行排序预处理。

在实现中,我们会用到取模来防止答案过大而溢出,这里需要用这样的小技巧来处理:

(a+b)modP=[(amodP)+(bmodP)]modP
(a×b)modP=[(amodP)×(bmodP)]modP

class Solution {
public:
    static constexpr int P = int(1E9) + 7;
    static constexpr int MAX_N = int(1E5) + 5;

    int f[MAX_N];

    void pretreatment() {
        f[0] = 1;
        for (int i = 1; i < MAX_N; ++i) {
            f[i] = (long long)f[i - 1] * 2 % P;
        }
    }

    int numSubseq(vector<int>& nums, int target) {
        pretreatment();

        sort(nums.begin(), nums.end());

        int ans = 0;
        for (int i = 0; i < nums.size() && nums[i] * 2 <= target; ++i) {
            int maxValue = target - nums[i];
            int pos = upper_bound(nums.begin(), nums.end(), maxValue) - nums.begin() - 1;
            int contribute = (pos >= i) ? f[pos - i] : 0;
            ans = (ans + contribute) % P;
        }

        return ans;
    }
};

排序+二分查找+快速幂

class Solution {	//C++
    int mod = 1e9+7;
public:
    int numSubseq(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int i = 0, j;
        unsigned long long count = 0;
        for(i = 0; i < nums.size(); ++i)
        {
            if(nums[i] > target/2+1)
                break;
            j = bs(nums,target-nums[i]);
            if(j != -1 && j >= i)
                count = (count+mypow(j-i))%mod;
        }
        return count;
    }
    
    int bs(vector<int>&a,int t)
    {
        int left = 0;
        int right = a.size()-1;
        int mid;
        while(left<=right)
        {
            mid = (left+right)/2;
            if(a[mid]>t)
            {
                right = mid -1;
            }
            else
            {
                if(mid == a.size()-1 || a[mid+1]>t )
                {
                    return mid;
                }
                else
                {
                    left = mid + 1;
                }
            }
        }
        return -1;
    }
    int mypow(int n)
    {

        long long s = 1, p = 2;
        while(n)
        {
            if(n&1)
                s *= p, s %= mod;
            p *= p;
            p %= mod;
            n /= 2;
        }
        return s;
    }

};
### 接龙游戏中的最长递增子序列算法 在接龙游戏中,寻找最长递增子序列的问题可以通过动态规划来解决。这个问题的关键在于定义状态转移方程以及如何处理特定条件下的比较逻辑。 #### 动态规划解法 为了找到满足特殊条件的最长递增子序列,在此情况下是指新加入元素的最高位数字需与前一元素最低位相同的情况,可以采用如下方式构建解决方案: - 定义 `dp` 数组用于记录以第 i 个字符结尾的最大长度。 - 初始化所有 `dp[i]=1` ,因为最短的有效序列也只包含自己本身。 - 遍历每一个可能成为序列末端的位置 i 并向前查找 j<i 是否存在符合条件的关系(即高位匹配),一旦发现则更新当前位置最大值 `dp[i] = max(dp[i], dp[j]+1)`[^4]。 下面是具体的 Python 实现代码: ```python def longest_dragon_sequence(nums): n = len(nums) # 辅助函数获数字的第一位和最后一位 def get_first_last_digit(num): first_digit = int(str(num)[0]) last_digit = num % 10 return first_digit, last_digit if not nums or n == 0: return 0 # DP table initialization dp = [1]*n for i in range(1,n): _, cur_end = get_first_last_digit(nums[i]) for j in range(i): prev_start,_=get_first_last_digit(nums[j]) if cur_end==prev_start and dp[j]+1>dp[i]: dp[i]=dp[j]+1 return max(dp) if dp else 0 ``` 这段程序实现了上述提到的方法论,并通过两个嵌套循环完成了对输入列表中每一对相邻项之间关系的评估。最终返回的结果是能够构成有效链条的最大数目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值