第一类Stirling数

首先设

$$S_k(n)=\sum_{i=0}^ni^k$$

根据第一类斯特林数的定义(P是排列数,C是组合数,s是Stirling)

$$C_n^k={P_n^k\over k!}={\sum_{i=0}^k(-1)^{i+k}s(k,i)n^i\over k!}$$

变形得

$$ n^k ={\sum_{i=0}^{k-1}(-1)^{i+k}s(k,i)n^i}-k! C_n^k$$

$n$ 从1取到n累加,

$$S_k(n)=\sum_{j=0}^n(k!C_j^k-\sum_{i=0}^{k-1}(-1)^{i+k}s(k,i)j^i)$$

拆括号

$$=k!\sum_{j=0}^nC_j^k-\sum_{i=0}^{k-1}(-1)^{i+k}s(k,i)\sum_{j=0}^nj^i$$

因为 $ C_{m+1}^{n+1}=C_m^n+C_{m}^{n+1} $,可推出 $\sum_{i=0}^nC_i^k=C_{n+1}^{k+1}$,

在转换为用排列数的

$$S_n(k)={P_{n+1}^{k+1}\over k+1}-\sum_{i=0}^{k-1}(-1)^{i+k}s(k,i)S_i(n)$$

那么我们只需要用 $O(k^2)$ 地预处理出第一类斯特林数,然后按k来递推了,边界是 $S_1(n)=n(n+1)/2$

主要运用了第一类斯特林数与排列式P的关系。

优点是可以避开除法,不用考虑模数有没有逆元,排列数的形式一定可以整除($k+1$ 个连续值相乘,其中肯定有 $k+1$ 的倍数)

//单次查询是 $O(k^2)$,多组测试就gg了,不知道有什么好的实现方法

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const ll mod = 1e9 + ;
const int maxk = + ;
ll n, k; ll stir[maxk][maxk];
void init()
{
stir[][] = stir[][] = ;
for(int i = ;i < maxk;i++)
for(int j = ;j <= i;j++)
stir[i][j] = (stir[i-][j-] + (i-)*stir[i-][j]) % mod;
} ll S[maxk]; //S[i]表示前n项的i次方之和
ll cal()
{
n %= mod;
S[] = (n+) * n / % mod; //假设 k>=1
for(int i = ;i <= k;i++)
{
//计算前面一坨
ll prod;
if(i > n) prod = ;
else
{
ll kk = i+;
prod = ;
for(ll j = ;j <= i;j++)
{
ll tmp = n+-j;
if(tmp % (i+) == ) prod = prod * (tmp/(i+)) % mod;
else prod = prod * tmp % mod;
}
} ll tmp = , sig;
for(int j = ;j < i;j++)
{
sig = (j+i)& ? - : ;
tmp = (tmp + sig*stir[i][j]*S[j]%mod + mod) % mod;
}
S[i] = ((prod - tmp)%mod + mod) % mod;
}
return S[k];
} int main()
{
init(); int T;
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &n, &k);
printf("%lld\n", cal());
} return ;
}

第二类Stirling数

首先需要证明一个式子

$$i^k = \sum_{j=1}^kS(k, j)*C_i^j*j!$$

证:对于一个 $i^k$,可以具体理解为把 $k$ 个不同的球放入 $i$ 个不同盒子里的方案数(允许空盒);

现在,枚举恰好有 $j$ 个盒子放有球,$j$ 可从1取到 $k$,所以方案数为 $\sum_{j=1}^kS(k, j)*C_i^j*j!$;

证毕。

$\sum \limits ^{n}_{i=0} i^k = \sum \limits _{i=0}^{n}\sum\limits _{j=1}^{k} S_{k,j}*C_{i,j}*j!$

然后讨论 $S(k, j)$ 的系数和:$\sum \limits ^{n}_{i=0} C_{i,j} *j!$,即 $j!* \sum\limits^{n}_{i=0} C_{i,j}$

已知:$\sum \limits_{i=0}^{n}C_{i,j}=C_{n+1,j+1}$

所以 $S(k, j)$ 的系数为 $j!*C_{n+1}^{j+1}$,

于是 $\sum \limits ^{n}_{i=0} i^k= \sum\limits_{j=1}^{k}S(k, j)*j!*C_{n+1}^{j+1}$.

变成排列数形式:$\displaystyle \sum \limits ^{n}_{i=0} i^k= \sum\limits_{i=1}^{k}S(k, i)* \frac{P_{n+1}^{i+1}}{{i+1}}$

然后预处理斯特林数就可以解决了.  

//同样单次查询是 $O(k^2)$

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const ll mod = 1e9 + ;
const int maxk = + ;
ll n, k; ll stir[maxk][maxk];
void init()
{
stir[][] = stir[][] = ;
for(int i = ;i < maxk;i++)
for(int j = ;j <= i;j++)
stir[i][j] = (stir[i-][j-] + j*stir[i-][j]) % mod;
} ll cal()
{
n %= mod;
ll sum = ;
for(int i = ;i <= k;i++)
{
ll prod;
if(i > n) prod = ;
else
{
prod = ;
for(int j = ;j <= i;j++)
{
ll tmp = n+-j;
if(tmp % (i+) == ) tmp /= (i+);
prod = prod * tmp % mod;
}
}
//printf("%lld\n", prod);
sum = (sum + stir[k][i]*prod) % mod;
}
return sum;
} int main()
{
init(); int T;
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &n, &k);
printf("%lld\n", cal());
} return ;
}

参考链接:

1. https://www.cnblogs.com/Zerokei/p/9726879.html

2. https://blog.csdn.net/lyd_7_29/article/details/75041818

最新文章

  1. 使用Bower作为Web包管理器
  2. http://www.cnblogs.com/yjmyzz/p/3941043.html
  3. WPF 文本框添加水印效果
  4. error at ::0 can&#39;t find referenced pointcut performance
  5. 使用sae定时执行Python脚本
  6. GDB调试方法(转)
  7. Failed to install *.apk on device &#39;emulator-5554&#39;: timeout
  8. 转:微信开发获取地理位置实例(java,非常详细,附工程源码)
  9. 实现多条件模糊查询SQL语句
  10. Get started with Google Analytics
  11. zookeeper的安装以及启动jps进程
  12. saiku 网站简介
  13. setfont()函数
  14. centos7下安装docker(26如何配置Health Check)
  15. centos7下安装docker(15.8docker跨主机容器通信总结)
  16. Guitar Pro特殊符号讲解之附点音符
  17. [Android Pro] Android P版本 新功能介绍和兼容性处理(三)Android Studio 3.0 ~ 3.2 其他特性
  18. [Leetcode] Template to rotate matrix
  19. 初识AutoMapper
  20. UVa 10129 Play on Words(并查集+欧拉路径)

热门文章

  1. 微信公众号开发 token 验证程序
  2. 2019-7-19 包、logging模块、hashlib(加密模块)、openpyxl模块、深浅拷贝
  3. C语言开发中常见报错的解决方案
  4. 使用adb命令对移动设备截图
  5. uwsgi重启shell脚本
  6. js的splice和delete
  7. java之aop
  8. Gulp 给所有静态文件引用加版本号
  9. Spring Security 解析(二) —— 认证过程
  10. 在Centos6.5上部署kvm虚拟化技术