【洛谷3746】【六省联考2017】组合数问题

题目描述

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

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

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

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

∑i=0infCnkik+rmodp\sum_{i=0}^{\inf} C_{nk}^{ik+r} mod pi=0infCnkik+rmodp的值。

输入输出格式

输入格式:

第一行有四个整数 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。

题解

一道矩阵加速的题。

对组合数的一个变形。原组合数公式是f[i][j]=f[i-1][j]+f[i-1][j-1]。由于这题是i*k+r,所以设f[i][j]表示i个物品中选x个物品,x满足x%k=j,所以f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k]。为什么呢??由原组合数公式可知,f[i][a*k+j]=f[i-1][a*k+j]+f[i-1][a*k+j-1]。所以sigmaf[i][a*k+j]=sigmaf[i-1][a*k+j]+sigmaf[i-1][a*k+j]。。因为设g[i][j]=sigma(a从0~一个值)f[a*k+j];(这里g[i][j]含义同上面f[i][j])。由于j-1会出现负的,也就是当j=0时,表示整除,由杨辉三角可知,前一个是k-1,所以f[i][j]=f[i-1][j]+f[i][(j-1+k)%k]。

递推式证完了,下面该说怎么推矩阵了。

像这种二维的递推,第一行矩阵一般把第二维都写出来再根据下一个推矩阵。就是由f[i][0],f[i][1],f[i][2].....f[i][k-1]看怎样推成f[i+1][0],f[i+1][1],f[i+1][2]......f[i+1][k-1],自己手推一下矩阵吧。最后结果就是f[0][r].因为第一行是f[i][0],f[i][1]....

下面就是矩阵加速了。。。不再赘述。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std; 
const int maxn=60;
ll n,p,k,r;
struct node{
	ll a[maxn][maxn];
}a,b,c,ans;
node work(node a,node b){
	memset(c.a,0,sizeof(c.a));
	
	for(int i=0;i<k;i++)
	for(int j=0;j<k;j++)
	for(int q=0;q<k;q++)
	c.a[i][j]=(c.a[i][j]+a.a[i][q]*b.a[q][j])%p;
	
	return c; 
}
void qpow(node a,ll b){
	while(b){
		if(b&1) ans=work(ans,a);
		a=work(a,a);
		b>>=1;
	}
}
int main(){
	cin>>n>>p>>k>>r;
	for(int i=0;i<k;i++){
		a.a[i][i]++;
		a.a[(i-1+k)%k][i]++;
	}
	ans=a;
	qpow(a,(ll)(n*k-1));
	printf("%lld\n",ans.a[0][r]);

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\],取证2022七省联考的考生将获得国PostgreSQL分会颁发的《国PostgreSQL认证考试技术能力证书》和工信部下属国电子工业标准化协会颁发的《国电子信息行业专业技术认定证书》两份证书。这两份证书具有较高的认可度和应用价值,可以在招投标、求职、职称晋升、抵税等方面发挥作用。此外,取证学员还可以享受全职业周期、全国覆盖的就业推荐服务。\[1\] 关于直径的计算,根据引用\[2\]和引用\[3\],在树的分裂情况下,最后的直径的长度可能是以下三种情况的最大值: 1. tree1的直径,假设tree1,原来最长链的一段为root1。 2. tree2的直径,假设tree2,原来最长链的一段为root2。 3. tree1的某一个点和tree2的某一个点连接的最长链。 在情况3,最优的连线方式是取tree1直径的一半、tree2直径的一半并连线。如果直径是奇,则需要向上取整。具体表达为:⌈Max1\[u\]/2⌉ + ⌈Max2\[v\]/2⌉ + 1。\[3\] 综上所述,取证2022七省联考的考生将获得两份证书,并且在计算直径时需要考虑三种情况,其情况3的最优连线方式是取tree1直径的一半、tree2直径的一半并连线,如果直径是奇,则需要向上取整。 #### 引用[.reference_title] - *1* [全国联考 | PostgreSQL初、级认证考试(5.22)通过考生公示](https://blog.csdn.net/weixin_46199817/article/details/117329421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [『树直径·树形DP』「四校联考」平衡树](https://blog.csdn.net/Ronaldo7_ZYB/article/details/90488429)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值