0%

「AGC041D」Problem Scores

题目链接

题意

求长度为 nn、满足以下条件的整数序列 AA 的个数:

  • i[1,n),AiAi+1\forall i\in[1,n),A_i\leq A_{i+1}
  • k[1,n)\forall k\in[1,n),任意 kkAA 中的数之和都严格小于任意 k+1k+1AA 中的数之和。

思路

易知第二个条件只要对于 k=n12k=\lfloor\frac {n-1}2\rfloor 满足即可。

设序列 AA 的差分数组为 dd,其中 d0=1d_0=1

根据题目要求易得:

  • i[1,n],di0\forall i\in[1,n],d_i\geq0
  • i=1k+1Ai>i=nk+1nAi\sum_{i=1}^{k+1}A_i>\sum_{i=n-k+1}^nA_i
  • i=0ndi=Ann\sum_{i=0}^nd_i=A_n\leq n,即 i=1ndi<n\sum_{i=1}^nd_i<n

由第二个限制得:

A1>i=1k(Ank+iAi+1)d1+1>i=3nk(i2)di+i=nk+1n(ni+1)did1i=3nk(i2)di+i=nk+1n(ni+1)di\begin{aligned} A_1&>\sum_{i=1}^k(A_{n-k+i}-A_{i+1})\\ d_1+1&>\sum_{i=3}^{n-k}(i-2)\cdot d_i+\sum_{i=n-k+1}^n(n-i+1)\cdot d_i\\ d_1&\geq\sum_{i=3}^{n-k}(i-2)\cdot d_i+\sum_{i=n-k+1}^n(n-i+1)\cdot d_i \end{aligned}

把第三个限制的 d1d_1 提出得:

d1<ni=2ndid_1<n-\sum_{i=2}^nd_i

此时我们便得出了 d1d_1 的取值范围(与个数):

{d1}=(ni=2ndi)(i=3nk(i2)di+i=nk+1n(ni+1)di)=n(d2+i=3nk(i1)di+i=nk+1n(ni+2)di)\begin{aligned} |\{d_1\}|&=\left(n-\sum_{i=2}^nd_i\right)-\left(\sum_{i=3}^{n-k}(i-2)\cdot d_i+\sum_{i=n-k+1}^n(n-i+1)\cdot d_i\right)\\ &=n-\left(d_2+\sum_{i=3}^{n-k}(i-1)\cdot d_i+\sum_{i=n-k+1}^n(n-i+2)\cdot d_i\right) \end{aligned}

问题转为,对于每种 d2,d3,,dnd_2,d_3,\dots,d_n,求和 {d1}|\{d_1\}|

wiw_idid_i 的系数,即 w={0,1,2,3,,nk1,k+1,k,,2}w=\{0,1,2,3,\dots,n-k-1,k+1,k,\dots,2\}

ww 为重量,2n2\sim n 的物体数量无限,做一次完全背包,最后计算出的 fif_i 即为括号内总和为 iid2,d3,,dnd_2,d_3,\dots,d_n 个数。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<cstdio>
using namespace std;
const int N=5000;
int n,k,p;
int w[N+1];
int f[N];
int res;
int main()
{
scanf("%d%d",&n,&p);
k=(n-1)/2;
w[2]=1;
for(int i=3;i<=n-k;++i) {
w[i]=i-1;
}
for(int i=n-k+1;i<=n;++i) {
w[i]=n-i+2;
}
f[0]=1;
for(int i=2;i<=n;++i) {
for(int j=0;j+w[i]<n;++j) {
f[j+w[i]]=(f[j+w[i]]+f[j])%p;
}
}
for(int i=0;i<n;++i) {
res=(res+1ll*(n-i)*f[i])%p;
}
printf("%d\n",res);
return 0;
}