zoukankan      html  css  js  c++  java
  • 【bzoj1925】[Sdoi2010]地精部落 组合数学+dp

    题目描述

    传说很久以前,大地上居住着一种神秘的生物:地精。 地精喜欢住在连绵不绝的山脉中。具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到N 之间的正 整数。 如果一段山脉比所有与它相邻的山脉都高,则这段山脉是一个山峰。位于边 缘的山脉只有一段相邻的山脉,其他都有两段(即左边和右边)。 类似地,如果一段山脉比所有它相邻的山脉都低,则这段山脉是一个山谷。 地精们有一个共同的爱好——饮酒,酒馆可以设立在山谷之中。地精的酒馆 不论白天黑夜总是人声鼎沸,地精美酒的香味可以飘到方圆数里的地方。 地精还是一种非常警觉的生物,他们在每座山峰上都可以设立瞭望台,并轮 流担当瞭望工作,以确保在第一时间得知外敌的入侵。 地精们希望这N 段山脉每段都可以修建瞭望台或酒馆的其中之一,只有满足 这个条件的整座山脉才可能有地精居住。 现在你希望知道,长度为N 的可能有地精居住的山脉有多少种。两座山脉A 和B不同当且仅当存在一个 i,使得 Ai≠Bi。由于这个数目可能很大,你只对它 除以P的余数感兴趣。

    输入

    仅含一行,两个正整数 N, P。

    输出

    仅含一行,一个非负整数,表示你所求的答案对P取余 之后的结果。

    样例输入

    4 7

    样例输出

    3


    题解

    自己yy的组合数学+dp

    首先我们可以思考,一个序列中,“1”所在的位置一定是山谷。那么“1”左侧一定是右面为山峰,“1”右侧一定是左面为山峰。

    然后我们可以发现左右是山峰的情况是对称的,所以相当于一边为山峰的情况。

    而且左右互不影响,是相同的子问题。

    所以对答案的贡献为“1”左边一边为山峰的方案数*“1”右边一边为山峰的方案数*从n-1个中选出“1”左边个数的数的方案数(组合数)。

    同理可以更新出一边为山峰的方案数、两边为山峰的方案数。

    状态转移方程(a[i]表示i个数的方案数,b[i]表示i个数中一边(不严格)为山峰的方案数,c[i]表示i个数中两边为山峰的方案数):

    $a[i]=sumlimits_{j=1}^ib[j-1]·b[i-j]·C_{i-1}^{j-1}\b[i]=sumlimits_{j=1}^ib[j-1]·c[i-j]·C_{i-1}^{j-1}\c[i]=sumlimits_{j=1}^ic[j-1]·c[i-j]·C_{i-1}^{j-1}$

    dp初值什么的看着办就好了。

    然后就可以O(n^2)求出答案啦。

    常数巨大。。。网上很多题解是分奇偶性讨论的,常数可能会小一些。

    注:题目不保证p是质数,所以需要递推组合数,这会导致MLE,需要使用滚动数组。

    #include <cstdio>
    #define N 4210
    typedef long long ll;
    ll a[N] , b[N] , c[N];
    int k[2][N];
    int main()
    {
    	int n , p , i , j;
    	scanf("%d%d" , &n , &p);
    	a[0] = b[0] = a[1] = b[1] = c[1] = k[1][0] = 1;
    	for(i = 2 ; i <= n ; i ++ )
    	{
    		k[i & 1][0] = 1;
    		for(j = 1 ; j <= i ; j ++ ) k[i & 1][j] = (k[(i & 1) ^ 1][j - 1] + k[(i & 1) ^ 1][j]) % p;
    		for(j = 1 ; j <= i ; j ++ )
    		{
    			a[i] = (a[i] + k[i & 1][j - 1] * b[j - 1] % p * b[i - j] % p) % p;
    			b[i] = (b[i] + k[i & 1][j - 1] * c[j - 1] % p * b[i - j] % p) % p;
    			c[i] = (c[i] + k[i & 1][j - 1] * c[j - 1] % p * c[i - j] % p) % p;
    		}
    	}
    	printf("%lld
    " , a[n]);
    	return 0;
    }
    

     

  • 相关阅读:
    systemctl命令
    linux下常用命令查看端口占用
    【PostgreSQL】存取jsonb
    tomcat内存溢出之PermGen space
    Spring事务传播机制
    java框架篇---spring aop两种配置方式
    Hibernate一对多实例
    Github 的系统内部都在用什么开源软件?
    这是一个关于软件开发的博客。
    JavaScript中数组的集合和映射
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7010821.html
Copyright © 2011-2022 走看看