POJ 1037 (计数 + DP) 一个美妙的栅栏
这道题总算勉勉强强看懂了,DP和计数都很不好想
DP部分:
称i根木棒的合法方案集合为S(i),第二根木棒比第一根长的方案称作UP方案,反之叫做DOWN方案
C[i][k][DOWN] 是S(i)中以第k短(而不是长度为k)的木棒打头的DOWN方案数。
假设S(i)中第一根木棒长为x,那么构成合法的方案数有两类:
- S(i - 1)中第一根木棒比x长的DOWN方案
- S(i - 1)中第一根木棒比x短的UP方案
有如下递推关系:
C[i][k][UP] = ∑ C[i-1][M][DOWN]
M = k ... i -1
C[i][k][DOWN] = ∑ C[i-1][N][UP]
N = 1… k-1
举个例子:
比如四根木棒,假设第一根木棒长度为2,在剩下的1 3 4中,比2长的3和4分别是S(3)中第2和第3短的。(要和C所定义的状态相对应)
所以上式的M和N的范围就是这样的
总的方案数就是:Sum{ C[n][k][DOWN] + C[n][k][UP] } k = 1.. n
计数部分:
扔掉这个题,考虑一下这个问题:
1 2 3 4全排列,求字典序的第10个
首先假设第一个数是1,那么后面有3! = 6 < 10种排列情况,所以打头的不是1。 继续假设是2,后面三个数也有6种排列情况, 6 + 6 ≥ 10,所以第一个数确定是2,此时跳过了第一个数为1的6种情况。
继续假设第二个数是1,后面有2! = 2种情况, 2 + 6 < 10,所以假设第二个数是3(注意2已经在第一个数中用过了),依旧是有2种情况, 8 + 2 ≥ 10,第二个数确定是3,跳过了10种情况。
后面因为10 ≥ 10,所以第三第四个数分别是1 4
所求的排列就是2 3 1 4
回到这个题上来:
前面已经求得了i个数中第k小打头的方案数,所以我们也完全可以模拟上面的思维过程来求解。
微调:以第i短的木棒作第k根时,有UP和DOWN两类方案,先用DOWN的方案数和C比较
//#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn = ;
const int UP = ;
const int DOWN = ;
long long C[maxn][maxn][]; void Init(int n)
{
memset(C, , sizeof(C));
C[][][UP] = C[][][DOWN] = ;
for(int i = ; i <= n; ++i)
for(int k = ; k <= i; ++k)
{
for(int M = k; M < i; ++M)
C[i][k][UP] += C[i - ][M][DOWN];
for(int N = ; N <= k - ; ++N)
C[i][k][DOWN] += C[i - ][N][UP];
}
} void Print(int n, long long c)
{
long long skipped = ;
int seq[maxn], used[maxn];
memset(used, , sizeof(used));
for(int i = ; i <= n; ++i)
{
long long oldVal = skipped;
int k, No = ;
for(k = ; k <= n; ++k)
{
oldVal = skipped;
if(!used[k])
{
++No;
if(i == )
skipped += C[n][No][UP] + C[n][No][DOWN];
else
{
if(k > seq[i - ] && (i == || seq[i - ] > seq[i - ]))
skipped += C[n - i + ][No][DOWN];
else if(k < seq[i - ] && (i == || seq[i - ] < seq[i - ]))
skipped += C[n - i + ][No][UP];
}
if(skipped >= c)
break;
}
}
used[k] = ;
seq[i] = k;
skipped = oldVal;
} for(int i = ; i < n; ++i) printf("%d ", seq[i]);
printf("%d\n", seq[n]);
} int main(void)
{
#ifdef LOCAL
freopen("1037in.txt", "r", stdin);
#endif int T, n;
long long c;
Init();
scanf("%d", &T);
while(T--)
{
scanf("%d %lld", &n, &c);
Print(n, c);
}
return ;
}
代码君
POJ 1037 (计数 + DP) 一个美妙的栅栏的更多相关文章
- poj 1037 三维dp
A decorative fence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7221 Accepted: 272 ...
- POJ 2229 计数DP
dp[i]代表是数字i的最多组合数如果i是一个奇数,i的任意一个组合都包含1,所以dp[i] = dp[i-1] 如果i是一个偶数,分两种情况讨论,一种是序列中包含1,因此dp[i]=dp[i-1]一 ...
- CodeForces 176B Word Cut (计数DP)
Word Cut Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit St ...
- [DP之计数DP]
其实说实在 我在写这篇博客的时候 才刚刚草了一道这样类型的题 之前几乎没有接触过 接触过也是平时比赛的 没有系统的做过 可以说0基础 我所理解的计数dp就是想办法去达到它要的目的 而且一定要非常劲非常 ...
- HDU 6377 度度熊看球赛 (计数DP)
度度熊看球赛 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- 计数dp
计数dp 计数类的$dp$没做过几个,所以之前都放到"思维"标签下了,后来发现原来这属于一类问题啊...搬过来了. 管道取珠:https://www.lydsy.com/Judge ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
- 【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值
[题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一 ...
- [ZJOI2010]排列计数 (组合计数/dp)
[ZJOI2010]排列计数 题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有 ...
随机推荐
- [翻译]The Neophyte's Guide to Scala Part 12: Type Classes
The Neophyte's Guide to Scala Part 12: Type Classes 过去的两周我们讨论了一些使我们保持DRY和灵活性的函数式编程技术,特别是函数组合,partial ...
- Unity3d 联通沃商店接入问题
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Loope ...
- Sqli-labs less 18
Less-18 本关我们这里从源代码直接了解到 对uname和passwd进行了check_input()函数的处理,所以我们在输入uname和passwd上进行注入是不行的,但是在代码中,我们看到了 ...
- 为什么主流网站无法捕获 XSS 漏洞?
二十多年来,跨站脚本(简称 XSS)漏洞一直是主流网站的心头之痛.为什么过了这么久,这些网站还是对此类漏洞束手无策呢? 对于最近 eBay 网站曝出的跨站脚本漏洞,你有什么想法?为什么会出现这样的漏网 ...
- HDU 2671 Can't be easier(数学题,点关于直线对称)
题目 //数学题//直线 y = k * x + b//直线 ax+by+c=0; 点 (x0,y0); 点到直线距离 d = (ax0+by0+c)/sqrt(a^2+b^2) /********* ...
- light oj 1140 - How Many Zeroes? 数位DP
思路:dp[i][j]:表示第i位数,j表示是否有0. 代码如下: #include<iostream> #include<stdio.h> #include<algor ...
- java volatile 和Transient 关键字
java关键字volatile volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同 ...
- 唉,还是Windows好
作为一个计算机专业的,常常抱怨Windows慢.一个系统用一段时间慢下来就重装,但是次次重装很麻烦,每次重装之后还得装软件. 另外,Windows比Linux占资源,所以前段时间就想以Linux为主要 ...
- Haproxy安装及配置
1.安装 # wget http://haproxy.1wt.eu/download/1.3/src/haproxy-1.3.20.tar.gz # tar zcvf haproxy-1.3.20.t ...
- CentOS编译安装Python3
前话 最近想学一下一门新的高级语言,无意中看到用python仿AIphaGo的github项目,就决定是他了. AIphaGo的Git传送门: https://github.com/Rochester ...