题目链接:传送门

题目:

题目描述

传说很久以前,大地上居住着一种神秘的生物:地精。

地精喜欢住在连绵不绝的山脉中。具体地说,一座长度为N的山脉H可分为从左到右的N段,每段有一个独一无二的高度Hi,其中Hi是1到N之间的正整数。

如果一段山脉比所有与它相邻的山脉都高,则这段山脉是一个山峰。位于边缘的山脉只有一段相邻的山脉,其他都有两段(即左边和右边)。

类似地,如果一段山脉比所有它相邻的山脉都低,则这段山脉是一个山谷。

地精们有一个共同的爱好——饮酒,酒馆可以设立在山谷之中。地精的酒馆不论白天黑夜总是人声鼎沸,地精美酒的香味可以飘到方圆数里的地方。

地精还是一种非常警觉的生物,他们在每座山峰上都可以设立瞭望台,并轮流担当瞭望工作,以确保在第一时间得知外敌的入侵。

地精们希望这N段山脉每段都可以修建瞭望台或酒馆的其中之一,只有满足这个条件的整座山脉才可能有地精居住。

现在你希望知道,长度为N的可能有地精居住的山脉有多少种。两座山脉A和B不同当且仅当存在一个i,使得Ai≠Bi。由于这个数目可能很大,你只对它除以P的余数感兴趣。

输入输出格式
输入格式: 输入文件goblin.in仅含一行,两个正整数N, P。 输出格式: 输出文件goblin.out仅含一行,一个非负整数,表示你所求的答案对P取余之后的结果。 输入输出样例 输入样例#: 输出样例#: 【数据规模和约定】 对于20%的数据,满足N≤; 对于40%的数据,满足N≤; 对于70%的数据,满足N≤; 对于100%的数据,满足3≤N≤,P≤1e9。

思路:又是似曾相识的那种dp。。分类讨论,转移方程显然。

如果在i之前的所有答案已经计算好了,那么更新i的时候就可以选择把i插入第k个和第k+1个之间,或者把i放在i-1个的旁边。

放置的时候因为i比之前的i-1个数都要大,所以它只能作为“山峰”出现,所以第k个和第k+1个必须都是山谷,放在旁边也是一样,相邻的必须是作为山谷的。

状态:

  f[i][0] 表示按题意放置好了i个数之后,左右两端都为山谷的方法数。

  f[i][1] 表示按题意放置好了i个数之后,左端山谷,右端山峰的方法数。

  f[i][2] 表示按题意放置好了i个数之后,左端山峰,右端山谷的方法数。

  f[i][3] 表示按题意放置好了i个数之后,左右两端都为山峰的方法数。

状态转移方程:

  f[i][0] += sum(f[j][0] * f[N-1-j][0] * Ci-1j);

  f[i][1] += sum(f[j][0] * f[N-1-j][1] * Ci-1j);

  f[i][2] += sum(f[j][2] * f[N-1-j][0] * Ci-1j);

  f[i][3] += sum(f[j][2] * f[N-1-j][1] * Ci-1j);

  N的范围是4500,其中的Ci-1j可以用杨辉三角跑出来,不过考虑到数据比较极限,可能会MLE,滚动数组优化之。

  据说可以扩展Lucas?。。。没学过赶紧去补(逃

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAX_N = + ; ll N, P;
ll f[MAX_N][];//第二维:0低低,1低高,2高低,3高高
ll C[][MAX_N]; int main()
{
cin >> N >> P;
memset(f, , sizeof f);
C[][] = ;
C[][] = C[][] = ;
for (int i = ; i <= N; i++) {
if (i == )
f[i][] = , f[i][] %= P;
if (i > ) {//加在边界
f[i][] += f[i-][], f[i][] %= P;
f[i][] += f[i-][], f[i][] %= P;
f[i][] += f[i-][] + f[i-][], f[i][] %= P;
}
if (i >= ) for (int j = ; j <= i; j++)
C[i&][j] = (C[(i&)^][j-] + C[(i&)^][j]) % P;
for (int j = ; j < i-; j++) {//j >= 1 && i-1-j >= 1
ll cur = C[(i&)^][j];
f[i][] += (f[j][]*f[i--j][])%P*cur, f[i][] %= P;
f[i][] += (f[j][]*f[i--j][])%P*cur, f[i][] %= P;
f[i][] += (f[j][]*f[i--j][])%P*cur, f[i][] %= P;
f[i][] += (f[j][]*f[i--j][])%P*cur, f[i][] %= P;
}
}
ll ans = ;
for (int k = ; k <= ; k++) {
ans += f[N][k], ans %= P;
}
cout << (ans+P)%P << endl;
return ;
}

P2467 [SDOI2010]地精部落 (dp+组合数)【扩展Lucas好难不会】的更多相关文章

  1. P2467 [SDOI2010]地精部落 DP

    传送门:https://www.luogu.org/problemnew/show/P2467 参考与学习:https://www.luogu.org/blog/user55639/solution- ...

  2. BZOJ 1925: [Sdoi2010]地精部落( dp )

    dp(i,j)表示1~i的排列中, 以1~j为开头且开头是下降的合法方案数 这种数列具有对称性, 即对于一个满足题意且开头是上升的n的排列{an}, 令bn = n-an+1, 那么{bn}就是一个满 ...

  3. Luogu P2467 [SDOI2010]地精部落 | 神奇的dp

    题目链接 DP 题目大意:给定一个数n,求1~n这n个整数的所有排列中有多少个波动数列,将这个数量%p后输出. 什么是波动数列呢?顾名思义,就是一个大.一个小.一个大.一个小--或者是一个小.一个大. ...

  4. [BZOJ1925][SDOI2010]地精部落(DP)

    题意 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到N ...

  5. P2467 [SDOI2010]地精部落

    题目描述 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为N的山脉H可分为从左到右的N段,每段有一个独一无二的高度Hi,其中Hi是1到N之间的正整数 ...

  6. luogu P2467 [SDOI2010]地精部落

    很有意思的dp计数题目. 思考一下发现开始时山峰和开始是山谷的方案数是相同的 所以我们只需要统计一个即可. 证明的话可以考虑对于任意一种开始时山峰的方案 每个数字变成n-a[i]+1 那么可以此方案还 ...

  7. 【BZOJ】1925: [Sdoi2010]地精部落 DP+滚动数组

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1925 题意:输入一个数N(1 <= N <= 4200),问将这些数排列成折线 ...

  8. Luogu2467 SDOI2010 地精部落 DP

    传送门 一个与相对大小关系相关的$DP$ 设$f_{i,j,0/1}$表示放了$i$个,其中最后一个数字在$i$个中是第$j$大,且最后一个是极大值($1$)或极小值时($0$)的方案数.转移: $$ ...

  9. 洛咕 P2467 [SDOI2010]地精部落

    同波浪,简单dp. 高度从1到n插入山脉,设f[i][j][k]表示插入了i个山脉,组成了j段,边界上有k个山脉的方案数. 那么新插入的山脉只会:插入在边界上且自己是一段.插入在边界上且与最左边的段相 ...

随机推荐

  1. swagger访问api, TypeError: Failed to fetch

    用swagger访问https://localhost:44360/api/ads/1, 得到的结果是 TypeError: Failed to fetch.一开始以为是后端代码问题,检查了好久,才发 ...

  2. 静态HTML总结

    第一章<META>标签: <meta http-equiv=”Content-Type” Content=”text/html;charset=gb2312”>------避免 ...

  3. IOS中position:fixed弹出框中的input出现光标错位的问题

    解决方案是 在弹框出现的时候给body添加fixed <style type="text/css"> body{ position: fixed; width: 100 ...

  4. oracle中查询当前系统时间用到的dual是什么?

    oracle我们查询当前系统时间的时候,经常用到dual,这个是什么东西呢? -- 查询系统时间 结果:2018/04/17 15:00:48 -- select sysdate from dual; ...

  5. 改变Cube的Shader下的Alpha值,实现Cube若隐若现的效果。

    private float rotaSpeed = 5f; private float timer = 1; private bool flag = true; private float delay ...

  6. bzoj1239

    题解: 首先计算出两两之间的距离 然后二分答案 然后贪心判断是否可以放置少于等于k个 代码: #include<bits/stdc++.h> using namespace std; ; ...

  7. FFT模板(无讲解)

    #include<bits/stdc++.h> using namespace std; ; const double pi=3.1415926535898; ],len; struct ...

  8. mq(1):简介

    1.mq的使用场景 以前的我,一直都没太搞明白,为什么我们那么需要消息队列,直到我看到了网友scienjus.的这个例子. 例子:假设用户在你的软件中注册,服务端收到用户的注册请求后,它会做这些操作: ...

  9. Saiku的基本使用介绍(三)

    Saiku的基本使用介绍(这里都是使用Admin用户登录系统) 1.启动安装好的Saiku  ( ./start-saiku.sh ) ,浏览器使用访问系统 http://localhost:8080 ...

  10. java阶段学习目标

    0-1年: <java编程思想> 1-2年: <大话设计模式>http://www.cnblogs.com/zuoxiaolong/p/pattern26.html <重 ...