Codeforces Round #722 (Div. 1) 1528B (数学推导dp)

题目链接: 题目地址

题意:一个数轴上有2n个点,你需要把这个2n个点用n个线段配对

n个线段配对后需要有两种关系之一: (1) 两线段长度相等 (2)一个线段包含另一个线段

问有x条线段时,有多少种配对方式

首先思考

  1. 若两线段长度相等:对于x条线段,配对2x个点, 若x为6,则有4种配对方案,分别是每条线段长度为(1,2,3,6) 。 可以画图理解一下, 这样我们可以发现dp[x] 有一方面贡献 可以+ x的因子个数

  2. 再思考一个线段包含另一条线段的情况,对于x条线段,我们可以思考发现,这种包含情况最多只有一个“团”, 意思也就是说,它们这些是连在一块的,没有单独成为多个独立的部分。

    考虑多个拱交叉的情况,他们的合法部分是多个拱的公共部分的dp值 所有,对于对于dp[x] 的贡献一部分来自于 i:1 ~ x-1 的dp[i] 累加值。 (为什么i不到x呢? i若等于了x,就没有了公共区间,回到了1的情况)

    所以 dp[x] = (累加)dp[1~x-1] + x的因子个数

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <map>
    using namespace std;
    //------------------------
    const int N = 1e6 + 10,mod = 998244353;
    typedef long long ll;
    ll f[N];
    ll num[N];
    int main()
    {
      
        int n; cin>>n;
        for(int i=1;i<N;i++){
           for(int j=i;j<N;j=j+i){
               num[j] =(num[j]+1)%mod;
           }
        }
        ll pre = 0;
        f[1]=1;
        f[2]=3;
        pre = 4;
        for(int i=3;i<=n;i++){
            f[i] = (f[i]+num[i]+pre)%mod;
            pre =(pre+f[i])%mod;
        }
        cout<<f[n]<<endl;
        return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值