• 源自 ditoly 大爷的 FJ 省队集训课件

Statement

  • 有 \(m\) 个正整数变量,求有多少种取值方案

  • 使得所有变量的和不超过 \(S\)

  • 并且前 \(n\) 个变量的值都不超过 \(t\)

  • 答案对 \(10^9+7\) 取模

  • \(m-n\le1000\) ,\(m\le 10^9\) ,\(t\le 10^5\) ,\(nt\le s\le 10^{18}\)

Solution

  • 由于 \(nt\le s\le 10^{18}\) ,所以我们的解可以表示成:

  • \[\sum_{x_1=1}^t\sum_{x_2=1}^t\dots\sum_{x_n=1}^t\binom{S-\sum_{i=1}^nx_i}{m-n}
    \]

  • 设 \(s=S-(m-n)+1-\sum_{i=1}^nx_i\)

  • 注意到上面的和式里面的组合数是一个关于 \(s\) 的多项式,具体地,它等于 \(\frac{s^{\overline{m-n}}}{(m-n)!}\)

  • 其中 \(n^{\overline m}\) 表示 \(n\) 的 \(m\) 次上升幂,即 \(\prod_{i=0}^{m-1}(n+i)\)

  • 由第一类斯特林数的生成函数可得,这个多项式的 \(i\) 次项系数为 \(\frac{\begin{bmatrix}m-n\\i\end{bmatrix}}{(m-n)!}\) ,其中 \(\begin{bmatrix}n\\m\end{bmatrix}\) 为第一类斯特林数,即把 \(n\) 个元素分成 \(m\) 个圆排列的方案数

  • 把组合数表示成多项式的形式之后,我们考虑如果我们求出了在前 \(n\) 个变量所有 \(t^n\) 种取值下对应的 \(s^i\) (\(0\le i\le m-n\))之和,那么问题就能很好地解决了

  • 考虑 DP:\(f[i][j]\) 表示 \(x_{1\dots i}\) 所有取值下 \((S-m+n+1-\sum_{k=1}^ix_k)^j\) 的和

  • 考虑如何从 \(f[i]\) 转移到 \(f[i+1]\)

  • 这个转移即枚举 \(x_{i+1}\) 的取值,设 \(s=S-m+n+1-\sum_{k=1}^ix_k\)

  • 可以发现:

  • \[\sum_{k=1}^t(s-k)^j=\sum_{k=0}^j(-1)^{j-k}\binom jks^ksum(j-k,t)
    \]

  • 其中 \(sum(p,n)=\sum_{i=1}^ni^p\) ,可以利用插值 \(O(p)\) 求出

  • 于是我们有了一个 DP 转移:

  • \[f[i+1][j]=\sum_{k=0}^j(-1)^{j-k}\binom jksum(j-k,t)f[i][k]
    \]

  • 把组合数拆开:

  • \[\frac{f[i+1][j]}{j!}=\sum_{k=0}^j\frac{(-1)^{j-k}sum(j-k,t)}{(j-k)!}\frac{f[i][k]}{k!}
    \]

  • 设多项式 \(F_i(x)=\sum_{j=0}^{m-n}f[i][j]x^j\) ,\(G(x)=\sum_{i=0}^{m-n}\frac{(-1)^isum(i,t)}{i!}x^i\)

  • 那么很容易得到 \(F_n(x)=G(x)^n\) ,倍增快速幂即可

  • 复杂度 \(O((m-n)^2\log n)\) 或 \(O((m-n)^2)\)

Code

#include <bits/stdc++.h>

const int N = 1010, rqy = 1e9 + 7;

typedef long long ll;

ll s;
int t, n, m, l, pw[N][N], f[N], fac[N], inv[N], invt[N], g[N], ans, S[N][N]; int qpow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = 1ll * res * a % rqy;
a = 1ll * a * a % rqy;
b >>= 1;
}
return res;
} int calc(int T)
{
int sum = 0, res = 0, al = 1;
for (int i = 1; i <= T + 2; i++) al = 1ll * al * (t - i + rqy) % rqy;
for (int i = 1; i <= T + 2; i++)
{
sum = (sum + pw[i][T]) % rqy;
if (i == t) return sum;
int delta = 1ll * al * invt[i] % rqy *
inv[i - 1] % rqy * inv[T + 2 - i] % rqy;
if (T + 2 - i & 1) delta = (rqy - delta) % rqy;
res = (1ll * delta * sum + res) % rqy;
}
return res;
} int main()
{
std::cin >> s >> t >> n >> m;
l = m - n; s -= l - 1;
f[0] = fac[0] = inv[0] = inv[1] = 1;
for (int i = 1; i <= l + 2; i++) fac[i] = 1ll * fac[i - 1] * i % rqy;
for (int i = 2; i <= l + 2; i++)
inv[i] = 1ll * (rqy - rqy / i) * inv[rqy % i] % rqy;
for (int i = 2; i <= l + 2; i++) inv[i] = 1ll * inv[i] * inv[i - 1] % rqy;
for (int i = 1; i <= l + 2; i++)
{
pw[i][0] = 1;
for (int j = 1; j <= l; j++) pw[i][j] = 1ll * pw[i][j - 1] * i % rqy;
}
for (int i = 1; i <= l + 2; i++) invt[i] = qpow((t - i + rqy) % rqy, rqy - 2);
for (int i = 1; i <= l; i++) f[i] = s % rqy * f[i - 1] % rqy;
for (int i = 0; i <= l; i++) f[i] = 1ll * f[i] * inv[i] % rqy;
for (int i = 0; i <= l; i++)
{
g[i] = 1ll * calc(i) * inv[i] % rqy;
if (i & 1) g[i] = (rqy - g[i]) % rqy;
}
while (n)
{
if (n & 1) for (int i = l; i >= 0; i--)
{
f[i] = 1ll * f[i] * g[0] % rqy;
for (int j = 1; j <= i; j++)
f[i] = (1ll * f[i - j] * g[j] + f[i]) % rqy;
}
for (int i = l; i >= 0; i--)
{
g[i] = 1ll * g[i] * g[0] % rqy;
if (i) g[i] = (g[i] + g[i]) % rqy;
for (int j = 1; j < i; j++)
g[i] = (1ll * g[i - j] * g[j] + g[i]) % rqy;
}
n >>= 1;
}
S[0][0] = 1;
for (int i = 1; i <= l; i++)
for (int j = 1; j <= i; j++)
S[i][j] = (1ll * S[i - 1][j] * (i - 1) + S[i - 1][j - 1]) % rqy;
for (int i = 0; i <= l; i++)
ans = (1ll * f[i] * fac[i] % rqy * S[l][i] + ans) % rqy;
return std::cout << 1ll * ans * inv[l] % rqy << std::endl, 0;
}

[组合数学][多项式][拉格朗日插值]count的更多相关文章

  1. 多项式函数插值:全域多项式插值(一)单项式基插值、拉格朗日插值、牛顿插值 [MATLAB]

    全域多项式插值指的是在整个插值区域内形成一个多项式函数作为插值函数.关于多项式插值的基本知识,见“计算基本理论”. 在单项式基插值和牛顿插值形成的表达式中,求该表达式在某一点处的值使用的Horner嵌 ...

  2. P4463 [集训队互测2012] calc 拉格朗日插值 dp 多项式分析

    LINK:calc 容易得到一个nk的dp做法 同时发现走不通了 此时可以考虑暴力生成函数. 不过化简那套不太熟 且最后需要求多项式幂级数及多项式exp等难写的东西. 这里考虑观察优化dp的做法. 不 ...

  3. luogu P5667 拉格朗日插值2 拉格朗日插值 多项式多点求值 NTT

    LINK:P5667 拉格朗日插值2 给出了n个连续的取值的自变量的点值 求 f(m+1),f(m+2),...f(m+n). 如果我们直接把f这个函数给插值出来就变成了了多项式多点求值 这个难度好像 ...

  4. P3270 [JLOI2016]成绩比较 容斥 数论 组合数学 拉格朗日插值

    LINK:成绩比较 大体思路不再赘述 这里只说几个我犯错的地方. 拉格朗日插值的时候 明明是n次多项式 我只带了n个值进去 导致一直GG. 拉格朗日插值的时候 由于是从1开始的 所以分母是\((i-1 ...

  5. 洛谷 P3270 - [JLOI2016]成绩比较(容斥原理+组合数学+拉格朗日插值)

    题面传送门 考虑容斥.我们记 \(a_i\) 为钦定 \(i\) 个人被 B 神碾压的方案数,如果我们已经求出了 \(a_i\) 那么一遍二项式反演即可求出答案,即 \(ans=\sum\limits ...

  6. Educational Codeforces Round 7 F - The Sum of the k-th Powers 拉格朗日插值

    The Sum of the k-th Powers There are well-known formulas: , , . Also mathematicians found similar fo ...

  7. 常系数齐次线性递推 & 拉格朗日插值

    常系数齐次线性递推 具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码. 概述 形式: \[ h_n = a_1 h_{n-1}+a_2h_{n-2}+...+a_kh_{n-k} \] ...

  8. 【XSY1537】五颜六色的幻想乡 数学 生成树计数 拉格朗日插值

    题目大意 ​ 有一个\(n\)个点\(m\)条边的图,每条边有一种颜色\(c_i\in\{1,2,3\}\),求所有的包括\(i\)条颜色为\(1\)的边,\(j\)条颜色为\(2\)的边,\(k\) ...

  9. 【BZOJ2655】calc DP 数学 拉格朗日插值

    题目大意 ​ 一个序列\(a_1,\ldots,a_n\)是合法的,当且仅当: ​ 长度为给定的\(n\). ​ \(a_1,\ldots,a_n\)都是\([1,m]\)中的整数. ​ \(a_1, ...

随机推荐

  1. python调用另一个文件中的代码,pycharm环境下:同文件夹下文件(.py)之间的调用,出现红线问题

    如何调用另一个python文件中的代码无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等, ...

  2. jQuery的使用及关于框架造型 专题

    Introduction 正如jQuery所宣称的一样,Write Less, Do More.很多时候我们喜欢用它来解决问题.但增加一个库必然意味着更大的网络负担,意味着更高的页面初始载入时间.并且 ...

  3. 关于hibernate5的映射文件和配置文件改变(转)

    转自:https://blog.csdn.net/m0_37840000/article/details/78823716 配置文件: <!DOCTYPE hibernate-configura ...

  4. lambda应用

    def test(a, b, func): result = func(a, b) print(result) test(10, 15, lambda x, y: x + y) #coding=utf ...

  5. python入门之字符串的魔法

    1.test="alex" v=test.capitalize() print(v)               //输出结果首字母大写 2.test1="alex&qu ...

  6. k8s集群———单master节点2node节点

    #部署node节点 ,将kubelet-bootstrap用户绑定到系统集群角色中(颁发证书的最小权限) kubectl create clusterrolebinding kubelet-boots ...

  7. CEF编译遇到的问题记录

    在使用vs2015编译cef官方代码的时候遇到很奇怪的问题, 我用官方的demo cefsimple例子程序编译debug版本 可以正常编译打开网页 正常的打开 我把官方的例子单独创建一个新的项目编译 ...

  8. Python数据分析:手把手教你用Pandas生成可视化图表

    大家都知道,Matplotlib 是众多 Python 可视化包的鼻祖,也是Python最常用的标准可视化库,其功能非常强大,同时也非常复杂,想要搞明白并非易事.但自从Python进入3.0时代以后, ...

  9. 1054 求平均值 (20 分)C语言

    本题的基本要求非常简单:给定 N 个实数,计算它们的平均值.但复杂的是有些输入数据可能是非法的.一个"合法"的输入是 [−1000,1000] 区间内的实数,并且最多精确到小数点后 ...

  10. CAP 3.0 版本发布通告

    前言 大家好,我们很高兴宣布 CAP 发布了 3.0 版本正式版. 自从上次 CAP 2.6 版本发布 以来,已经过去了几个月的时间,关注的朋友可能知道,在这几个月的时间里,也发布了几个预览版的 3. ...