[六省联考2017]组合数问题

题面

给定 n , p , k , r n,p,k,r n,p,k,r ,求 ∑ i = 0 ∞ C n k i k + r m o d p \sum_{i=0}^{\infin}C_{nk}^{ik+r} mod p i=0Cnkik+rmodp
n ≤ 1 0 9 n\le 10^9 n109 r < k ≤ 50 r<k\le 50 r<k50 2 ≤ p ≤ 2 30 − 1 2\le p\le 2^{30}-1 2p2301

题解

看数据范围发现大概率是矩阵乘。

C有一个递推式, C m n = C m − 1 n + C m − 1 n − 1 C_{m}^{n}=C_{m-1}^{n}+C_{m-1}^{n-1} Cmn=Cm1n+Cm1n1

f ( k , r , l ) = ∑ i = 0 ∞ C l i k + r f(k,r,l)=\sum_{i=0}^{\infin}C_{l}^{ik+r} f(k,r,l)=i=0Clik+r

f ( k , r , l ) = ∑ i = 0 ∞ C l i k + r f(k,r,l)=\sum_{i=0}^{\infin}C_{l}^{ik+r} f(k,r,l)=i=0Clik+r = ∑ i = 0 ∞ ( C l − 1 i k + r + C l − 1 i k + r − 1 ) =\sum_{i=0}^{\infin}(C_{l-1}^{ik+r}+C_{l-1}^{ik+r-1}) =i=0(Cl1ik+r+Cl1ik+r1) = f ( k , r , l − 1 ) + f ( k , ( r − 1 + k ) % k , l − 1 ) =f(k,r,l-1)+f(k,(r-1+k)\%k,l-1) =f(k,r,l1)+f(k,(r1+k)%k,l1)

得出这个递推式就很容易矩阵乘了。

感觉这题不应该紫题。。我调一些蓝题的时间都比这题长

放代码:

# include <bits/stdc++.h>
using namespace std;
namespace fastio{
	template<typename tn> void read(tn &a){
	    tn x=0,f=1;char c=' ';
	    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	    for(;isdigit(c);c=getchar() ) x=x*10+c-'0';
	    a=x*f;
	}
	template<typename tn> void print(tn a){
	    if(a<0) putchar('-'),a=-a;
	    if(a>9) print(a/10);
	    putchar(a%10+'0');
	}
};
using namespace fastio;
const int N=55;
#define int long long
int n,p,k,r;
int f[N],a[N][N]; 
void mul(int f[N],int a[N][N]){
	int c[N];
	memset(c,0,sizeof(c));
	for(int j=0;j<k;j++)
	    for(int h=0;h<k;h++)
	        c[j]=(c[j]+(long long)f[h]*a[h][j])%p;
	memcpy(f,c,sizeof(c));
}
void mulself(int a[N][N]){
	int c[N][N];
	memset(c,0,sizeof(c));
	for(int i=0;i<k;i++)
	    for(int j=0;j<k;j++)
	        for(int h=0;h<k;h++)
	            c[i][j]=(c[i][j]+(long long)a[i][h]*a[h][j])%p;
	memcpy(a,c,sizeof(c));
}
signed main(){
	read(n);
	read(p);
	read(k);
	read(r);
	for(int i=0;i<k;i++) a[i][i]++,a[i][(i+1)%k]++;
	f[0]=1;
	long long l=n*k;
	for(;l;l>>=1){
		if(l&1) mul(f,a);
		mulself(a);
	}
	print(f[r]);
	return 0;
}

中间WA了两次:

  1. 要开long long
  2. k=1时有一个特判,可以直接把=1改成++
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值