题目描述

组合数 C_n^mCnm​ 表示的是从 n 个互不相同的物品中选出 m 个物品的方案数。举个例子,从 (1;2;3) 三个物品中选择两个物品可以有 (1;2);(1;3);(2;3) 这三种选择方法。根据组合数的定义,我们可以给出计算组合数 C_n^mCnm​ 的一般公式:

C_n^m = \frac{n!}{m!(n-m)!}Cnm​=m!(n−m)!n!​

其中 n! = 1 × 2 × · · · × n。(特别的,当 n = 0 时, n! = 1 ,当 m > n 时, C_n^m =0Cnm​=0 )

小葱在 NOIP 的时候学习了 C_i^jCij​ 和 k 的倍数关系,现在他想更进一步,研究更多关于组合数的性质。小葱发现, C_i^jCij​ 是否是 k 的倍数,取决于 C_i^j mod kCij​modk 是否等于 0,这个神奇的性质引发了小葱对 mod 运算(取余数)的兴趣。现在小葱选择了是四个整数n; p; k; r,小葱现在希望知道

\sum_{i=0}^{\inf} C_{nk}^{ik+r} mod p∑i=0inf​Cnkik+r​modp

的值。

输入输出格式

输入格式:

第一行有四个整数 n; p; k;r,所有整数含义见问题描述。

输出格式:

一行一个整数代表答案。

输入输出样例

输入样例#1: 复制

2 10007 2 0
输出样例#1: 复制

8
输入样例#2: 复制

20 10007 20 0
输出样例#2: 复制

176

说明

• 对于 30% 的测试点, 1 ≤ n; k ≤ 30, p 是质数;

• 对于另外 5% 的测试点, p = 2;

• 对于另外 5% 的测试点, k = 1;

• 对于另外 10% 的测试点, k = 2;

• 对于另外 15% 的测试点, 1 ≤ n ≤ 10^3; 1 ≤ k ≤ 50, p 是质数;

• 对于另外 15% 的测试点, 1 ≤ n × k ≤ 10^6, p 是质数;

• 对于另外 10% 的测试点, 1 ≤ n ≤ 10^9; 1 ≤ k ≤ 50, p 是质数;

• 对于 100% 的测试点, 1 ≤ n ≤ 10^9; 0 ≤ r < k ≤ 50; 2 ≤ p ≤ 2^30 − 1。

作为省选的T3出题人居然给了60分的暴力分,太良心了QWQ..

不过正解是死活想不到啊

设$C[i][j]$表示从$i$个元素中,拿所有满足$x \%k=j $ 的 $x$个元素的方案数

那么对于第$i$个元素,

不选的方案数为$C[i-1][j]$

选的方案数为$C[i-1][(j-1+k)%k]$

很显然

可以用矩阵快速幂优化

然后就做完了

这题的关键是把杨辉三角的递推与题目中给出的式子相结合,找到题目中式子的一般规律,

进而通过更高科技的算法优化

注意$k=1$的特殊情况

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int MAXN=1e6;
inline int read()
{
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int N,mod,k,r;
int C[][];
struct Matrix
{
int a[][];
Matrix(){memset(a,,sizeof(a));}
};
Matrix mul(Matrix x,Matrix y)
{
Matrix c;
for(int kk=;kk<=k-;kk++)
for(int i=;i<=k-;i++)
for(int j=;j<=k-;j++)
c.a[i][j]=(c.a[i][j]+x.a[i][kk]*y.a[kk][j]%mod)%mod;
return c;
}
void out(Matrix x)
{
for(int i=;i<=k-;i++,puts("\n"))
for(int j=;j<=k-;j++)
printf("%d ",x.a[i][j]);
}
Matrix fastpow(Matrix a,int p)
{
Matrix base;
for(int i=;i<=k;i++) base.a[i][i]=;
while(p)
{
if(p&) base=mul(base,a);
a=mul(a,a);
p>>=;
}
return base;
}
main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#endif
N=read(),mod=read(),k=read(),r=read();
Matrix tmp;
for(int i=;i<=k-;i++)
tmp.a[i][i]=tmp.a[i][i+]=;
tmp.a[k-][]++;tmp.a[k-][k-]++;
Matrix ans;
ans.a[][]=;
tmp=fastpow(tmp,N*k);
ans=mul(ans,tmp);
printf("%lld",ans.a[][r]);
return ;
}

最新文章

  1. Grunt(页面静态引入的文件地址的改变探究)-V2.0
  2. SQL如何将A,B,C替换为&#39;A&#39;,&#39;B&#39;,&#39;C&#39;
  3. augustus, gene prediction, trainning
  4. [你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理
  5. 笔记二、本地git命令
  6. sql 截取两个字符串之间的字符
  7. mongodb write 【摘自网上,只为记录,学习】
  8. SQL Server 分组后取Top N
  9. STM32F051 IAP源代码分享
  10. IOSJSBRIGE商品内容模板
  11. centos java环境搭建
  12. Redhat 6.3上安装CMake
  13. Eclipse MAT内存分析工具(Memory Analyzer Tool)
  14. vector的 []
  15. 简要描述 JavaScript 中定义函数的几种方式
  16. PHP中报500错误时如何查看错误信息
  17. [LeetCode] 693. Binary Number with Alternating Bits_Easy
  18. auxre7使用安装
  19. Selenium UI 举例 getCssValue
  20. STORJ 有实际应用

热门文章

  1. SQL Server-聚焦强制索引查询条件和Columnstore Index
  2. 关于Java学习
  3. 如何把数值或者对象添加到ArrayList集合
  4. WPF 利用RichTextBox 打印出不同颜色的文本
  5. python编写简单的html登陆页面(4)
  6. VS Code编写html(2)
  7. jsmind实现思维导图,和echars 的tree图类似
  8. C语言提高 (7) 第七天 回调函数 预处理函数DEBUG 动态链接库
  9. GDI 线段绘制示例程序
  10. 【BZOJ4864】【BJWC2017】神秘物质 - Splay