Enigmatic Partition【二阶差分】-2020牛客暑期多校8

题意:

对于一个数 (n) 可以将其拆分为 (m) 个数,(n=a_1+a_2+...+a_m),要求满足:

  • (a_i) 是整数,对于所有的 (a_i)(1leq a_i leq n)
  • (a_ileq a_{i+1}leq a_i+1) 对于所有的 (a_i(i<m))
  • (a_m=a_1+2)

定义 (f(n)) 比赛 (n) 的划分方案数,对于给定的 (l)(r) ,求出 (sum_{i=l}^{r}{f(i)})
(1leq lleq r leq 10^5)

分析:

考虑二阶隔项差分,然后往回求出原数列,并预处理前缀和。
这篇博客里讲的很详细:
https://blog.csdn.net/zhangchizc/article/details/107784622?spm=1001.2101.3001.4242

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
ll f[N<<2], sum[N];
void init()
{
    int maxn = 1e5;
    for (int m = 3; m <= maxn;m++)
    {
        for (int a = m; a <= maxn;a+=m)
        {
            f[a + 3]++;
            f[a + m + 1]--;
            f[a + m + 2]--;
            f[a + 2 * m]++;
        }
    }
    for (int i = 3; i <= maxn;i++)
        f[i] += f[i - 2];
    for (int i = 2; i <= maxn;i++)
        f[i] += f[i - 1];
    for (int i = 1; i <= maxn;i++)
        sum[i] = sum[i - 1] + f[i];
}
int main()
{
    int T,l,r,cas=0;
    init();
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &l, &r);
        printf("Case #%d: %lld
",++cas,sum[r] - sum[l - 1]);
    }
    return 0;
}

参考博客:
https://blog.csdn.net/fztsilly/article/details/107813922

原文地址:https://www.cnblogs.com/1024-xzx/p/13444642.html