[AGC049D] Convex Sequence

[AGC049D] Convex Sequence

题意

题目写得很清楚。

思路

省流

做原凸包的二阶导数 \(\{c_i\}\),有 \(\sum_{k=1}^n \frac{k(k+1)}{2} c_k=M\)

枚举凸包最低点 \(p\),钦定 \(p\) 一定是最低点最左边的那个点,将 \([1,p]\) 归入左部,将 \([p+1,n]\) 归入右部。因此左部需要填 \(p-1\) 个数,其中 \(c_{p-1}\) 为正数。右部需要填 \(n-p\) 个数。所有 \(c_i\) 非负。

答案取生成函数的 \([x^m],[x^{m-n}],\cdots\)

可以使用生成函数来做。

第二个条件就是 \(a_i-a_{i-1} \le a_{i+1}-a_i\),即 \(\{ a_i \}\) 是下凸壳。

下凸壳这个要求不好处理。

我们先考虑只有右下凸壳的情况,即斜率非负。

对原数列做差分数组 \(\{ b_i \}\),得到 \(\{ b_i \}\) 单调不减。

然而单调不减依然不好维护,对 \(\{ b_i \}\) 再做差分数组 ${c_i} $,要求 \(c_i\) 非负。

然而 \(\sum c_i\) 是未知的,我们只知道 \(\sum a_i = M\),考虑推出 \(\sum f_i c_i = M\)

\[\begin{aligned} M&=\sum_{i=1}^n a_i\\ &=\sum_{i=1}^n \sum_{j=1}^i b_i\\ &=\sum_{j=1}^n (n-j+1) b_j\\ &=\sum_{j=1}^n (n-j+1) \sum_{k=1}^j c_k\\ &=\sum_{k=1}^n \frac{(n-k+1)(n-k+2)}{2} c_k \end{aligned} \]

换元 \(k:=n-k+1\)

\[\sum_{k=1}^n \frac{k(k+1)}{2} c_k=M \]

容易发现 \(c_k\)\(0\)\(k\) 最大到 \(\sqrt{M}\)。思考一下发现这是符合直觉的。而 \(k>\sqrt{M}\)\(c_k=0\)

写出生成函数:

每个 \(c_{k}\) 可以取值 \([0,inf)\)。对指数的贡献就是 \(x^{\frac{k(k+1)}{2}\times c_k}\)

\[[x^M] F(x) = \prod_{k=1}^{\min(n,\sqrt{M})} \frac{1}{1-x^{\frac{k(k+1)}{2}}} \]

这玩意只关心 \(M\) 项,而且是 \(\sqrt{M}\) 个多项式相乘,考虑递推求解。

定义 \(t:=\frac{k(k+1)}{2},F(x)_n := \prod_{k=1}^{n} \frac{1}{1-x^{t}}\)

\[\begin{aligned} F(x)_n& = \frac{1}{1-x^t} F(x)_{n-1}\\ F(x)_n (1-x^t) &= F(x)_{n-1}\\ \end{aligned} \]

对于每一项系数 \(f_{n-1,i}\)\(f_{n,i} - f_{n,i-t} = f_{n-1,i}\)

因此得到递推式子 \(f_{n,i} = f_{n-1,i} + f_{n,i-t}\)

由于多项式指数为负的系数总是零,因此无需讨论指数为负的情况。

因此可是通过 \(O(M)\) 的时间从 \(F(x)_{n-1} \to F(x)_n\)

总时间复杂度 \(O(M \sqrt{M})\)

对于凸壳斜率正负都存在的情况,我们枚举凸壳最低点 \(p\),左右分开算。

\[[x^M] \prod_{k=1}^{\min(a,\sqrt{M})} \frac{1}{1-x^{\frac{k(k+1)}{2}}} \prod_{k=1}^{\min(n-a,\sqrt{M})} \frac{1}{1-x^{\frac{k(k+1)}{2}}} \]

本质不同的情况只有 \(O(\sqrt{M})\) 种,而且每次 \(p\) 向右移 \(1\) 的时候,相当于式子乘上或者除以 \(\frac{1}{1-x^{\frac{k(k+1)}{2}}}\),可以类似上面 \(O(M)\) 递推求出新的多项式。

乘上 \(\frac{1}{1-x^t}\)\(f_i' = f_i + f_{i-t}'\)

除以 \(\frac{1}{1-x^t}\)\(f_i' = f_i - f_{i-t}\)

然后答案取 \(x_M\) 的系数。

实现的时候发现不好做,因为一个序列可能拥有多个最低点 \(p\),因此会算重。

我的做法是钦定 \(p\) 一定是最低点最左边的那个点。将 \([1,p]\) 归入左部,将 \([p+1,n]\) 归入右部,因此左部需要填 \(p-1\) 个数,其中 \(c_{p-1}\) 非零。右部需要填 \(n-p\) 个数,没有额外限制。

还有一个问题是如果要保证原凸壳的二阶导数非负,就不可以算上最低点位置的二阶导数。因此会造成凸壳整体上移或者下移,二阶导数不变的情况。那么我们可以枚举上移的量,答案加上 \([x^m],[x^{m-n}],\cdots\)

code

注意实际上 \(k\) 的上界为 \(O(\sqrt{2M})\),因为有 \(\iint c_k \le M\)。大概是这么写的吧。

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace ababab {
    constexpr int N=1e5+7,mod=1e9+7;
    int add(int a,int b) { return a+b>=mod ? a+b-mod : a+b; }
    void _add(int &a,int b) { a=add(a,b); }
    int n,m;
    int f[N<<1],_f[N<<1];
    int lim;
    int laa,lab;
    int ans;
    void solvemul(int t) {
        memcpy(_f,f,sizeof(f));
        rep(i,0,m<<1) f[i]=add(_f[i],i-t>=0?f[i-t]:0);
    }
    void solvediv(int t) {
        memcpy(_f,f,sizeof(f));
        rep(i,0,m<<1) f[i]=add(_f[i],i-t>=0?mod-_f[i-t]:0);
    }
    void solvechange(int t) {
        memcpy(_f,f,sizeof(f));
        rep(i,0,m<<1) f[i]=i+t<=(m<<1)?f[i+t]:0;
    }
    void solvechange2(int t) {
        memcpy(_f,f,sizeof(f));
        rep(i,0,m<<1) f[i]=i-t>=0?add(_f[i-t],f[i-t]):0;
    }
    void main() {
        sf("%d%d",&n,&m);
        f[0]=1;
        lim=ceil(sqrt(m))*2;
        lab=lim;
        rep(i,1,lim) solvemul(i*(i+1)/2);
        rep(a,1,min(n,lim+1)) {
            int b=n-a;
            int _a=a-1, _b=min(b,lim);
            if(laa!=_a) {
                rep(k,laa+1,_a) {
                    solvechange((k-1)*k/2);
                    solvechange2(k*(k+1)/2);
                }
                laa=_a;
            } 
            if(lab!=_b) {
                rep(k,_b+1,lab) solvediv(k*(k+1)/2);
                lab=_b;
            }
            for(int j=m;j>=0;j-=n) _add(ans,f[j]);
        }
        pf("%d\n",ans);
    }
}
int main() {
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("my.out","w",stdout);
    #endif
    ababab :: main();
}
posted @ 2024-12-15 09:24  liyixin  阅读(14)  评论(0编辑  收藏  举报