题目是要我们求出如下柿子:

\[\sum_{i=0}^{n}C_{nk}^{ik+r}
\]

考虑k和r非常小,我们能不能从这里切入呢?

如果你注意到,所有组合数上方的数\(\%k==r\),那么是不是可以从\(DP\)开始呢?

跟据上述性质,我们可以得到暴力\(DP\):

考虑组合数的实际意义是在n个数中选出m个,那么我们可以设\(dp[i][j]\)表示在i个元素中,选了\(m\%k==j\)的方案数

转移就可以用\(dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1]\)了,根据你的欧气,你可以获得\(45-70\)分的分数

由于空间原因,暴力代码用了滚动数组;由于文章长度原因,暴力代码省去了一些没必要的东西

\(Brute:\)

#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
int n, m, p, r, dp[55];
int main() {
n = read(), p = read(), m = read(), r = read(), dp[0] = 1;
rep(i, 1, n * m) {
int pax = dp[m - 1];
drep(j, 1, m - 1) dp[j] = (dp[j - 1] + dp[j]) % p;
dp[0] = (dp[0] + pax) % p;
}
printf("%d", dp[r]);
return 0;
}

那么我们还可以怎么优化呢?

考虑到\(N*K\)达到了\(5*10^{10}\),我们考虑矩阵优化:

我们怎么从\(dp[i - 1][0……m-1]\)推出\(dp[i][0……m-1]\)呢?

只需要构造一个\(50*50\)的矩阵,第一行中第一列和最后一列为\(1\),其余第\(i\)行第\(i\)列和第\(i-1\)列为1,其他都是\(0\),问题便可以解决

注意,矩阵初始化的时候不能直接\(=1\),要考虑\(k=1\)的情况

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int read() {
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(int i = s; i <= t; ++ i)
int n, m, p, r;
struct Martix {
int a[55][55];
void Init() { rep(i, 1, m) a[i][i] = 1; }
void Mem() { memset(a, 0, sizeof(a)); }
}Ans, Base;
Martix Mul(Martix a, Martix b) {
Martix c; c.Mem();
rep(i, 1, m) rep(j, 1, m) rep(k, 1, m) c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % p) % p;
return c;
}
Martix Pow(Martix a, int b) {
Martix R; R.Mem(), R.Init();
while(b) {
if(b & 1) R = Mul(R, a);
a = Mul(a, a), b >>= 1;
}
return R;
}
signed main() {
n = read(), p = read(), m = read(), r = read();
++ Base.a[1][1], ++ Base.a[1][m], ++ Ans.a[1][1];
rep(i, 2, m) ++ Base.a[i][i], ++ Base.a[i][i - 1];
Ans = Mul(Ans, Pow(Base, n * m));
printf("%lld", Ans.a[1][1 + r]);
return 0;
}

最新文章

  1. 【python】实用函数啥的
  2. 让linux中的程序崩溃时生成core文件
  3. VC包含目录、附加依赖项、库目录及具体设置
  4. ORA-01034: ORACLE not available如何解决
  5. motto4
  6. android listview和button,ImageButton等有事件的控件的总结
  7. openwrt无线中继教程
  8. Template模式
  9. table表格中加入&lt;a&gt;标签,使内容上下居中的方法。
  10. 《Velocity 模板使用指南》中文版[转]
  11. Render To Texel Baker
  12. iOS开发:使用Block在两个界面之间传值(Block高级用法:Block传值)
  13. C#Css/Js静态文件压缩--Yui.Compressor.Net
  14. java 显示视频时间--玩的
  15. C++著名类库和C++标准库介绍
  16. Java 9 揭秘(3. 创建你的第一个模块)
  17. 201521123006 《java程序设计》 第10周学习总结
  18. python3基础(二)
  19. Spring.net的一些感悟
  20. 微信硬件平台(八) 3 ESP8266向微信服务器请求设备绑定的用户

热门文章

  1. Oracle数据库Schema的简介
  2. 使用poi统计工作职责
  3. 【开发笔记】- Java中关于HashMap的元素遍历的顺序问题
  4. 【开发工具】- Windows下多个jdk版本切换
  5. 【面试突击】-Redis常见面试题(二)
  6. js-Date对象(九)
  7. 红米手机使用应用沙盒一键修改sdk信息
  8. git 命令行操作(之前整理在有道的笔记)
  9. sql server快捷键添加
  10. PHP java时间戳转php时间戳