一类暴力搜索解决生成函数问题解法简记
更新日志
2025/06/26:开工。前言
做到两道这个套路,感觉有点经典,简单记录一下。
概念
考虑一个生成函数展开后如果有一部分不好简化,且大概长下面这个形式:
\[(1-a_1x^{k_1})(1-a_2x^{k_2})\dots(1-a_{n}x^{k_n})
\]
并且 \(n\) 足够小使得 \(2^n\) 可以通过,那么就可以考虑这种做法。
思路
考虑深搜暴力展开上式后未合并的每一项。
具体的,对每一个因子,递归乘上 \(1\) 和乘上 \(-ax^k\) 的两种情况(举个例子),实时记录当前项的系数和次数。
我们最后肯定是要求某个次项的系数,上述递归完全部因子后,将当前项与生成函数的其余部分结合,更新要求的项的系数答案。
例题
直接给出生成函数:
\[(1-x^{f_1+1})(1-x^{f_2+1})\dots(1-x^{f_n+1})\sum_{i=0}^{\infty}\binom{n+i-1}{n-1}x^i
\]
组合数部分显然可以 \(O(n)\) 求得,我们考虑用上述解法解决左边部分,得到一 \(k\) 次项后乘上组合数部分 \(s-k\) 次项系数即可。注意 \(k\le s\)。
inline mint calc(ll k){
    mint res=1;
    rep(i,1,n-1)res*=(k+i)%mod;
    res*=iv[n-1];
    return res;
}
void dfs(int now,mint val,ll key){
    if(key>s)return;
    if(now==n+1)return ans+=val*calc(s-key),void();
    dfs(now+1,val,key);dfs(now+1,0-val,key+f[now]+1);
}
inline void Main(){
    read(n,s);
    rep(i,1,n)read(f[i]);
    dfs(1,1,0);
    put(ans);
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号