zoukankan      html  css  js  c++  java
  • [luoguP2606] [ZJOI2010]排列计数(DP)

    传送门

    如果能够根据题意看出这是一个堆的话,那么就有些思路了。。

    首先堆顶必须是最小元素,然后左右儿子可以预处理出来都有多少个数,

    把剩余的数任意分配给两个儿子,用排列组合即可

    dp(now) = dp(now << 1) * dp(now << 1 | 1) * C(sum[now] - 1, sum[now << 1])

    #include <cstdio>
    #define N 5000001
    #define LL long long
    
    int n;
    LL p, inv[N], A[N], B[N], s[N];
    
    inline LL C(int x, int y)
    {
    	return A[x] * B[y] % p * B[x - y] % p;
    }
    
    inline LL dp(int now)
    {
    	if(!s[now] || s[now] == 1) return 1;
    	return dp(now << 1) * dp(now << 1 | 1) % p * C(s[now] - 1, s[now << 1]) % p;
    }
    
    int main()
    {
    	int i, j;
    	scanf("%d %lld", &n, &p);
    	inv[1] = A[1] = A[0] = B[0] = B[1] = 1;
    	for(i = 2; i <= n; i++)
    	{
    		inv[i] = -(p / i) * inv[p % i] % p;
    		A[i] = A[i - 1] * i % p;
    		B[i] = B[i - 1] * inv[i] % p;
    	}
    	for(i = 1; i <= n; i++)
    		for(j = i; j; j >>= 1) s[j]++;
    	printf("%lld
    ", (dp(1) + p) % p);
    	return 0;
    }
    

      

  • 相关阅读:
    Aspect Oriented Programming
    jsp01
    监听器
    Java编写验证码
    servlet07
    MySQL02
    MySQL01
    Java的jdk1.6与jre1.8中存在的差异
    登陆验证和二级联动
    ajax和json
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/8202355.html
Copyright © 2011-2022 走看看