HDU 5226 Tom and matrix

一、题目

题目描述

i = x 1 x 2 j = y 1 y 2 C ( i , j ) \sum_{i=x_1}^{x_2}\sum_{j=y_1}^{y_2}C(i,j) ,规定当 i < j i<j C ( i , j ) = 0 C(i,j)=0 ,答案模一个质数 p p

数据范围

1 x 1 , y 1 , x 2 , y 2 1 e 5 , 1 p 1 e 9 1\leq x_1,y_1,x_2,y_2\leq1e5,1\leq p\leq1e9

二、解法

首先证明一个结论: i = a b C ( i , k ) = C ( b + 1 , k + 1 ) C ( a , k + 1 ) \sum_{i=a}^b C(i,k)=C(b+1,k+1)-C(a,k+1) ,利用 C ( i , j ) = C ( i 1 , j 1 ) + C ( i 1 , j ) C(i,j)=C(i-1,j-1)+C(i-1,j) ,可以证明 i = 1 b C ( i , k ) = C ( b + 1 , k + 1 ) \sum_{i=1}^bC(i,k)=C(b+1,k+1) (画个图就行了),然后差分一下得证。

我们枚举 k k ,然后用直接算组合数就行了。

#include <cstdio>
#define int long long
const int M = 100005;
int read()
{
    int x=0,flag=1;char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int x1,y1,x2,y2,ans,p,inv[M],fac[M];
void init(int n)
{
	inv[0]=inv[1]=fac[0]=1;
	for(int i=2;i<=n;i++) inv[i]=inv[p%i]*(p-p/i)%p;
	for(int i=2;i<=n;i++) inv[i]=inv[i]*inv[i-1]%p;
	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%p;
}
int C(int n,int m)
{
	if(n<m) return 0;
	return fac[n]*inv[m]%p*inv[n-m]%p;
}
int work(int n,int m)
{
	if(m==0) return 1;
	return work(n/p,m/p)*C(n%p,m%p)%p;
}
signed main()
{
	while(~scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&p))
	{
		ans=0;
		init(x2+1);
		for(int i=y1;i<=y2;i++)
		{
			ans=(ans+work(x2+1,i+1)-work(x1,i+1))%p;
		}
		printf("%d\n",(ans+p)%p);
	}
}
原创文章 430 获赞 14 访问量 1万+

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/105683642
tom
今日推荐