[BZOJ3377]geng4512膜你题1:子集

【问题描述】

azui大爷在quack大爷的带领下开始玩集合了,可是他太懒了,不想做quack大爷布置的作业题,便拿来给你做了:S 集合中有n个不同的元素,我们从1-n标号。考虑S 的子集Si,j,将这些子集排成一个r行c列矩阵的样子。其中第一行为S1,1,S1,2,…,S1,c,第二行为S2,1,S2,2,..,S2,c一直到第r行为Sr,1, Sr,2,…, Sr,c。这些集合还满足对于在一行中左右相邻的两个集右,左侧是右侧的子集,即Si,j∈Si,j+1。这些集合还满足对于在一列中上下相邻的两个集合,上方是下方的子集,即Si,j∈Si+1,j。问对于S 的全部子集,有多少可能的情况排成上述的矩阵(每个子集可以重复使用),结果模109 +7 输出。你一定知道这么简单的题目怎么做,快帮帮azui大爷吧。


【输入格式】

一行三个数n,r,c.


【输出格式】

一个数表示答案。


【样例输入】

1 2 2


【样例输出】

6


【样例解释】

1

2

3

4

如上图标号后,有:1是2和3的子集,1,2,3都是4的子集。
用0表示空集,1表示元素1,从左到右是1、2、3、4的话,有以下6种情况

0000 0001 0011 0101 0111 1111


【数据范围】
对于10%的数据,r*c*n <= 16
对于20%的数据,r*c <= 16, n <= 100
对于另20%的数据,r=1, c<=1000000
对于另10%的数据,n=1

对于100%的数据,r, c <= 1000000, n <= 10^9



题解:线性求逆元:

i*A[i] ≡ 1 (mod p), 求i的逆元A[i]


A[i] ≡ i^(-1) (mod p)
令p=k*i+r ( r<i,1<i<p )
k*i+r≡0 (mod p)
(k*i+r) * i^(−1)*r^(−1) ≡ 0 * i^(−1)*r^(−1) (mod p)
k*r^(−1)+i^(−1) ≡ 0 (mod p)
i^(−1) ≡ -k*r^(−1) (mod p)

i^(−1) ≡ -(p/i)*(p%i)^(−1) (mod p)


即:A[i]=-(p/i)*A[p%i];


#include<cstdio>
typedef long long LL;
const int Mod=1e9+7;
LL n, r, c;

LL Mul( LL a, LL b ) {
	LL res=0;
	for( int i=1; i<=b; i<<=1, a=(a<<1)%Mod )
		if( b&i ) res=(res+a)%Mod;
	return res;
}

LL Ksm( LL b, LL p ) {
	LL res=1;
	while(p) {
		if( p&1 ) res=Mul( res, b );
		b=Mul( b, b ); p>>=1;
	}
	return res;
}

LL Fac( LL w ) {//阶乘factorial
	LL res=1;
	for( LL i=2; i<=w; i++ ) res=res*i%Mod;
	return res;
}

LL Inv( LL w ) {//求逆元
	if( w==1 ) return 1;
	return  ( Mod-Mod/w*Inv( Mod%w )%Mod )%Mod;//(num+Mod)%Mod避免负数

}

LL C( LL n, LL m ) {//C( c+r, r )%Mod
	return Fac(n) * Inv( Fac(m) )%Mod * Inv( Fac(n-m) )%Mod;
/*C(n,m)%Mod
== n! / (m!*(n-m)!) % Mod
== n! * (m!)^(-1) * ((n-m)!)^(-1) % Mod
== n! * Inv(m!) * Inv((n-m)!) % Mod*/
}

int main() {
	scanf( "%I64d%I64d%I64d", &n, &r, &c );
	printf( "%I64d\n", Ksm( C(r+c,r), n ) );
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值