题意:
对于一个数 (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