srm 565 div 2

250 水题

500 枚举每个怪打还是不打,dfs水过

1000 

题意:定义一个序列S[0] = N,length(S) = H,且 A[i+1] | A[i],给定N,H,问有多少个数列满足要求。

将N质因子分解后,发现A[i+1]的质因子集是A[i]的子集,,然后就可以想象有n个盒子,每个盒子里有ai个球,每次选任意个(可以是0个),求有多少种选法。每个盒子都可以看成是独立的。然后就可以看成是n个未知数相加,求解的个数经典问题。

这里求质因子的方法要注意一下

然后要计算C(a,b)%m,a,m,都很大,这里用逆元的方法解决,有 a^(p-1) % p == 1这一结论。。。

class DivisibleSequence{
public: 
	int count(int N, int H)
	{
		ll ans = 1;
		for(int i = 2; i*i <= N; i++){
			int cnt = 0;
			while(N % i == 0){
				cnt++;
				N /= i;
			}
			ans = ans * Cal(cnt,H) % mod;
		}
		if(N != 1) ans = ans * Cal(1,H) % mod;
		return ans ;
	}
	// n个因子,每个因子ai个
	// 对于第i个因子,x1 + x2 + .. + xh = n
	// C(n+h,h-1)
	// (h..h+n)!/ (1..n+1)!
	int qpow(ll a,int b)
	{
		ll ans = 1;
		while(b){
			if(b & 1) ans = ans * a % mod;
			a = a * a % mod;
			b >>= 1;
		}
		return ans ;
	}
	int inv(int n)
	{
		return qpow(n,mod-2);
	}
	// C(n+h-1,h-1) = C(n+h-1,n)
	// h....n+h-1
	// 1....n
	int Cal(int n,int h)
	{
		ll ans = 1;
		for(int i = h; i <= n+h-1; i++)
			ans = ans * i % mod;
		for(int i = 1; i <= n; i++)
			ans = ans * inv(i) % mod;
		return ans ;
	}

};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值