bzoj 2013 上升计数

题意: 给一个数集和一个数d,问满足下列要求的排列数(相同的数要区分):  a[i]+d>=a[i+1] ( i in [1,n) )

因为数的给出顺序不重要,所以先排序,假如我们已经解决了前i个数的答案,考虑前i+1个数,即我们可以将第i+1个数放在哪,然后发现对于前i个数的每一种方案,我们都可以选择将第i+1个数放在大于等于它-d的数的上面,从而形成一种新的方案(当然直接可以放在地上),然后就完了.

收获:

  1. 对于不重要的东西(如原序列的顺序),可以直接舍弃

  2. 减小问题规模,发现小规模的问题和比它大一数据规模的问题之间的联系.

 1 /**************************************************************
 2     Problem: 2013
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:988 ms
 7     Memory:10492 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <algorithm>
12 #define N 620010
13 #define Mod 1000000009
14 using namespace std;
15
16 typedef long long dnt;
17
18 int n;
19 dnt h[N], d;
20 dnt dp[N];
21
22 int main() {
23     scanf( "%d%lld", &n, &d );
24     for( int i=1; i<=n; i++ )
25         scanf( "%lld", h+i );
26     sort( h+1, h+1+n );
27     dnt cur = 1;
28     for( int i=1; i<=n; i++ ) {
29         int j = lower_bound( h+1, h+i, h[i]-d ) - h;
30         cur = cur*(i-j+1) % Mod;
31     }
32     printf( "%lld\n", cur );
33 }
34 

时间: 2024-10-13 04:29:00

bzoj 2013 上升计数的相关文章

BZOJ 1833 数字计数(统计[a,b]每个数字出现次数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1833 题意:给定区间[a,b].求区间内0到9每个数字出现的次数. 思路:f[i][j]表示到后i位是否全 0(j=1表示i位之前全0)这个状态某个数字出现的次数,p[i][j]表示这个状态后面有多少个数字.那么当前枚举到的数字为要统计的数字时,答案加 上后面还有多少种数字,即下一个状态的p值.那么我们枚举要统计的数字依次统计即可. i64 f[20][2],p[20][2]; i64

bzoj 2013

http://www.lydsy.com/JudgeOnline/problem.php?id=2013 最初看这个题的时候,以为神题不可做,然后去找yzjc..然后做法过于简单了(' '      ) 先排个序.假设我们已经将前i个砖块有一个合法的方案,那么加入第i + 1个砖块的时候可加入的位置都是一定的,都为在1 ~ i 中 > l[i +1] - D 的砖块的个数,因为插在中间的时候由于保证了所有已经加入的砖块的长度都小于i + 1块,所以只和上一块有关,所以只要满足上面那个式子就可以了

BZOJ 1016 最小生成树计数

Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的).由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了. Input 第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数.每个节点用1~n的整数编号.接下来的m行,每行包含两个整数:a, b, c,表示节点a

bzoj 1008 组合计数

正难则反 前面定后面就定->枚举开头 1 /************************************************************** 2 Problem: 1008 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:0 ms 7 Memory:804 kb 8 ****************************************************************/ 9 1

bzoj 2013 华容道

比较难的题单独拉出来讲咯 华容道 描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的: 有些棋子是固定的,有些棋子则是可以移动的: 任何与空白的格子相邻(有公共的

BZOJ 1833 数字计数(数位DP)

经典数位DP模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath>

BZOJ 2111 排列计数

f[i]=f[l]*f[r]*C(size[l]+size[r],size[l]). 需要lucas. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1000050 using namespace std; long long n,mod,inv1[maxn],inv2[maxn],f[maxn],size[maxn]; long

BZOJ 2839 集合计数 容斥原理

题目大意:给定n个元素,求交集大小为k的集合的集合共有多少种 考虑容斥原理 计算交集大小至少为i的集合有多少种 首先需要选出i个元素 方案为C(n,i) 其它2^(n-i)个集合每个可选可不选 一共2^[2^(n-i)]种 故答案为Σ[k<=i<=n]C(n,i)C(i,k)*2^[2^(n-i)] #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

bzoj 1833 数字计数

题目大意: 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次 思路: 不知道黄学长他们的dp都是怎么dp的 搞神的方法太强啦 %%% 数位乱搞.. 推了公式,然后每一位直接套用公式 每一位分3种情况 小于该位数字的直接+10的位数次方 等于的+10的位数减一次方再加上后面几位构成数字那么多 大于的+10的位数减一次方 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath>