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 ;
}
};