[bzoj4870] [Shoi2017]组合数问题
2017-07-09 21:18
453 查看
题目大意
略…分析
注意到一个重要的条件:t< k那么根据组合数的意义,可以理解为从nk件物品里取若干件,满足取出物件数量模k等于t的方案数。
又发现k很小,然后可以设出DP:设f[i][j]表示前i件物品取的件数模k等于j的方案数。转移很显然。
用矩阵乘法可以做到O(k3lognk)
然而这个DP满足结合律,即假设我们已经求出了数组f
[],可以求出f[2n][],列出的式子是一个卷积形式。于是可以暴力求这个卷积,同时用类似快速幂的方法求f[nk][]。时间复杂度O(k2lognk)
可以开大数据范围用NTT加速到O(klogklognk)(划
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=55; typedef long long LL; int n,mo,k,r,f ,g ; void quick(LL x) { if (!x) return; quick(x>>1); memset(g,0,sizeof(g)); for (int i=0;i<k;i++) { for (int j=0;j<k;j++) { int t=(i+j)%k; g[t]=(g[t]+(LL)f[i]*f[j])%mo; } } memcpy(f,g,sizeof(f)); if (x&1) { memset(g,0,sizeof(g)); for (int i=0;i<k;i++) { g[i]=(g[i]+f[i])%mo; g[(i+1)%k]=(g[(i+1)%k]+f[i])%mo; } memcpy(f,g,sizeof(f)); } } int main() { scanf("%d%d%d%d",&n,&mo,&k,&r); f[0]=1; quick((LL)n*k); printf("%d\n",f[r]); return 0; }
相关文章推荐
- BZOJ4870:[SHOI2017]组合数问题——题解
- bzoj 4870: [Shoi2017]组合数问题 动态规划
- [BZOJ4870][Shoi2017]组合数问题 dp+矩阵乘
- BZOJ4870: [Shoi2017]组合数问题
- BZOJ4870: [Shoi2017]组合数问题
- BZOJ 4870 [Shoi2017]组合数问题 ——动态规划 矩阵乘法
- BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法
- bzoj 4870: [Shoi2017]组合数问题
- 【jzoj5215】【BZOJ4870】【Shoi2017】【GDOI2018模拟7.9】【组合数问题】【矩阵快速幂】
- [bzoj4870][Shoi2017]组合数问题
- bzoj4870 [Shoi2017]组合数问题(dp+矩阵倍增)
- BZOJ4870 [Shoi2017]组合数问题 【组合数 + 矩乘】
- 【bzoj4870】[Shoi2017]组合数问题 dp+快速幂/矩阵乘法
- BZOJ 4870 [Shoi2017] 组合数问题
- 【BZOJ4870】[Shoi2017]组合数问题 动态规划(矩阵乘法)
- bzoj 4870: [Shoi2017]组合数问题
- BZOJ 4870: [Shoi2017]组合数问题 (递推+矩阵快速幂)
- bzoj4870 [Shoi2017]组合数问题
- [DP 倍增] BZOJ 4870 [Shoi2017]组合数问题
- [BZOJ4870][SHOI2017]组合数问题 DP+矩阵快速幂