leetcode 1359. Count All Valid Pickup and Delivery Options(有效的快递序列数目)

该博客探讨了一种编程问题,涉及统计满足特定条件的订单配送序列。问题要求确保每个订单的配送服务总是在收件服务之后。文章提供了两种解决方案:一是通过找规律和组合数学计算序列数,二是使用动态规划的方法。博主给出了详细的思路和代码实现,并且强调了在处理大数时防止溢出的重要性。

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

给你 n 笔订单,每笔订单都需要快递服务。

请你统计所有有效的 收件/配送 序列的数目,确保第 i 个物品的配送服务 delivery(i) 总是在其收件服务 pickup(i) 之后。

由于答案可能很大,请返回答案对 10^9 + 7 取余的结果。

示例 1:

输入:n = 1
输出:1
解释:只有一种序列 (P1, D1),物品 1 的配送服务(D1)在物品 1 的收件服务(P1)后。
示例 2:

输入:n = 2
输出:6
解释:所有可能的序列包括:
(P1,P2,D1,D2),(P1,P2,D2,D1),(P1,D1,P2,D2),(P2,P1,D1,D2),(P2,P1,D2,D1) 和 (P2,D2,P1,D1)。
(P1,D2,P2,D1) 是一个无效的序列,因为物品 2 的收件服务(P2)不应在物品 2 的配送服务(D2)之后。
示例 3:

输入:n = 3
输出:90

提示:
1 <= n <= 500

方法一:
找规律。
首先把P1~Pn做好排列,共有n! 种排列方法。
然后拿出其中一例,讨论Dn的排列
P1,P2,P3,… , Pn
首先看Dn,它只有一处能放,它需放在Pn后面,得到P1,… ,Pn-1,Pn,Dn
然后Dn-1,它能放在Pn前面,Pn后面Dn前面,Dn后面,共3种
再看Dn-2,可验证有5种
后面就不一一验证了,一共1,3,5,… ,2i-1种
上面只是一种P的排列,那P一共n!种排列方式,
所以P和D结合起来一共n!* (1 * 3 * 5 * … * (2n-1))种
注意结果要用long型,因为在取模之前有可能已经溢出
参考链接

    public int countOrders(int n) {
        long result = 1;
        int mod = 1000000007;
        
        for(int i = 1; i <= n; i++) {
            result *= i;  //n!
            result %= mod;
            result *= (2*i - 1);
            result %= mod;
        }
        return (int)(result %= mod);
    }

方法二:
DP
代码和上面一样,只是思维方式不一样
令DP[i]表示有i个点时有多少种排列
如果有i-1个物品,那么因为同时有P和D,所以一共会有2(i-1)个点
现在看第i个物品,会引入Pi和Di
Pi引入后,如果Pi放在index=0处,那么Di可放的位置有2i-1处(index=0后面有2i-2个点,它们加上左右两端的缝隙有2i-2+1处缝隙可放)
如果Pi放在index=1处,Di可放的位置有2i-2处

如果Pi放在最后,Di也只能放在最后1处
一共有1+2+…+(2i-1) = i * (2i-1)
再来一个Pi+1的话,就会在此基础上再乘(i+1) * (2I+1)
所以dp[i] = dp[i-1] * i * (2i-1)

代码和上面一样
参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值