UOJ#204 【APIO2016】Boat

Time Limit: 70 Sec  Memory Limit: 256 MB
Submit: 559  Solved: 248

Description

在首尔城中,汉江横贯东西。在汉江的北岸,从西向东星星点点地分布着个划艇学校,编号依次为到。每个学校都

拥有若干艘划艇。同一所学校的所有划艇颜色相同,不同的学校的划艇颜色互不相同。颜色相同的划艇被认为是一

样的。每个学校可以选择派出一些划艇参加节日的庆典,也可以选择不派出任何划艇参加。如果编号为的学校选择

派出划艇参加庆典,那么,派出的划艇数量可以在Ai至Bi之间任意选择(Ai<=Bi)。值得注意的是,编号为i的学

校如果选择派出划艇参加庆典,那么它派出的划艇数量必须大于任意一所编号小于它的学校派出的划艇数量。输入

所有学校的Ai、Bi的值,求出参加庆典的划艇有多少种可能的情况,必须有至少一艘划艇参加庆典。两种情况不同

当且仅当有参加庆典的某种颜色的划艇数量不同

Input

第一行包括一个整数N,表示学校的数量。接下来N行,每行包括两个正整数,用来描述一所学校。其中第行包括的

两个正整数分别表示Ai,Bi(1<=Ai<=Bi<=10^9),N<=500

Output

输出一行,一个整数,表示所有可能的派出划艇的方案数除以1,000,000,007得到的余数

Sample Input

2
1 2
2 3

Sample Output

7

HINT

Source

动态规划

看着题解懵X一个多小时,我这么弱已经没救了吧

枚举数量显然无力,我们得考虑将整段区间一起处理,于是先将区间离散化

将派船看作在限定区间里选一个数,设f[i][j][k]表示当前枚举到第i个学校,最大船数在第j段,这段里选了k个数的方案数。

$ f[i][j][k]=f[i-1][j][k]+f[i-1][j][k-1]* \frac {C(len[j],k)}{C(len[j],k-1)} $

特殊处理 $ f[i][j][1]=f[i-1][j][1] + (\sum_{a=1}^{j-1}  \sum_{k=0}^{i-1} f[i-1][a][k] )*len[j] $

第一维可以滚动优化掉

第一个式子的组合数,约分一下变成了(len-k+1)/k ,预处理500以内的逆元即可。

第二个式子用前缀和优化。

然后大概就能过了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define LL long long
 6 using namespace std;
 7 const int mod=1e9+7;
 8 const int mxn=1105;
 9 int read(){
10     int x=0,f=1;char ch=getchar();
11     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
12     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
13     return x*f;
14 }
15 int inv[mxn];
16 void init(){
17     inv[0]=inv[1]=1;
18     for(int i=2;i<mxn;i++){
19         inv[i]= ((-mod/i)*(LL)inv[mod%i]%mod+mod)%mod;
20     }
21     return;
22 }
23 int n;
24 int c[mxn][mxn];
25 struct seg{
26     int L,R;
27 }a[mxn];
28 int pos[mxn],sz=0,len[mxn];
29 int f[mxn][mxn],g[mxn];
30 int num[mxn];
31 int main(){
32 //    freopen("boat.in","r",stdin);
33 //    freopen("boat.out","w",stdout);
34     int i,j;
35     n=read();
36     init();
37     for(i=1;i<=n;i++){
38         a[i].L=read()-1;a[i].R=read();
39         pos[++sz]=a[i].L;pos[++sz]=a[i].R;
40     }
41     sort(pos+1,pos+sz+1);
42     sz=unique(pos+1,pos+sz+1)-pos-1;
43 //    for(i=1;i<=sz;i++)printf("%d",pos[i]);
44     for(i=1;i<=n;i++){
45         a[i].L=lower_bound(pos+1,pos+sz+1,a[i].L)-pos;
46         a[i].R=lower_bound(pos+1,pos+sz+1,a[i].R)-pos;
47     }
48     for(i=1;i<=sz;i++)len[i]=pos[i]-pos[i-1];
49     f[0][1]=1;
50     for(i=1;i<=sz;i++)g[i]=1;
51     for(i=1;i<=n;i++){
52         for(j=a[i].L+1;j<=a[i].R;j++){
53             num[j]++;
54             for(int k=num[j];k>1;k--)
55                 f[j][k]=((LL)f[j][k]+(LL)f[j][k-1]*(len[j]-k+1)%mod*(LL)inv[k])%mod;
56             f[j][1]=((LL)f[j][1]+(LL)g[j-1]*len[j]%mod)%mod;
57         }
58         for(j=a[i].L+1;j<=sz;j++){
59             g[j]=g[j-1];
60             for(int k=num[j];k;k--){
61                 g[j]=((LL)g[j]+f[j][k])%mod;
62             }
63         }
64     }
65     g[sz]--;if(g[sz]<=0)g[sz]+=mod;
66     printf("%d\n",g[sz]);
67     return 0;
68 }
时间: 2024-11-07 20:59:04

UOJ#204 【APIO2016】Boat的相关文章

UOJ #206. 【APIO2016】Gap

有 NN 个严格递增的非负整数 a1,a2,…,aNa1,a2,…,aN(0≤a1<a2<?<aN≤10180≤a1<a2<?<aN≤1018).你需要找出 ai+1−aiai+1−ai(0≤i≤N−10≤i≤N−1)里的最大的值. 你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息.关于查询函数的细节,请根据你所使用的语言,参考下面的实现细节部分. 你需要实现一个函数,该函数返回 ai+1−aiai+1−ai(0≤i≤N−10≤i≤N−1)中

【APIO2016】Gap

[APIO2016]Gap 交互题 对于30%的数据,直接从s=0,t=1e18开始,每次让s=mn+1,t=mx-1,每一次可以得到两个,可以在(n+1)/2的时间内得到 对于其他数据,我们先求出最大最小值,求出len=(mx-mn)/(n-1),这相当与是一个"平均数",如果我将区间分为若干段长度为len的区间,只记录每个区间内的最大值和最小值,这样被漏算的那些点,他们最多有len-1的贡献,而这个还达不到平均数,所以肯定不会影响答案,所以就可以在3*n以内求出序列有用的部分了.

UOJ#122【NOI2013】树的计数

[NOI2013]树的计数 链接:http://uoj.ac/problem/122 按BFS序来,如果$B_i$与$B_{i-1}$必须在同一层,那么贡献为0,必须在不同层那么贡献为1,都可以贡献为0.5. 因为$B_i$与$B_{i-1}$相邻,所以对方案数的改变最多+1. 必须在不同层,即$D(B_{i-1})>D(B_i)$ 都可以,$B_i$能往下移一层,不改变BFS序以及DFS序: 作为兄弟,父亲必须一样(即$D(B_{i-1})==D(B_i)-1$),不然会改变DFS序. 作为儿

UOJ#130 【NOI2015】荷马史诗 K叉哈夫曼树

[NOI2015]荷马史诗 链接:http://uoj.ac/problem/130 因为不能有前缀关系,所以单词均为叶子节点,就是K叉哈夫曼树.第一问直接求解,第二问即第二关键字为树的高度. #include< cstdio > #include< algorithm > typedef unsigned long long ull; template inline void read(T&x) { x=0;bool f=0;char c=getchar(); while

UOJ#126【NOI2013】快餐店

[NOI2013]快餐店 链接:http://uoj.ac/problem/126 YY了一个线段树+类旋转卡壳的算法.骗了55分.还比不上$O(n^2)$暴力T^T 题目实际上是要找一条链的两个端点,链的中点处建快餐店.要求这两个端点的最短距离为其他所有点对的最短距离的最大值. 这条链不经过环,那答案就是环上挂的某个子树的子树直径.至少大于等于最大的树直径.树DP一发得到Ans1 经过环,显然不会饶环一圈.这个链必定由这样构成:x,y为环上两点.x子树最长链->x-y最短路-y子树最长链.可以

uoj #5. 【NOI2014】动物园 kmp

#5. [NOI2014]动物园 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/5 Description 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班,让动物们学习算法. 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S它的长度为L.我们可以在O(L)的时间内求出一个名为next

UOJ #2. 【NOI2014】起床困难综合症 数位DP

第二次做NOI的题... .预处理+数位DP #2. [NOI2014]起床困难综合症 id=2" style="">统计提交情况 id=2#tab-statement" style="color:rgb(85,85,85); text-decoration:none; position:relative; display:block; padding:10px 15px; margin-right:2px; line-height:1.428571

Uoj #131. 【NOI2015】品酒大会 后缀数组,并查集

#131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 nn 杯鸡尾酒.这 nn 杯鸡尾酒排成一行,其中第 ii 杯酒 (1≤i≤n1in) 被贴上了一个标签 sisi,每个标签都是 2626 个小写英文字母之一.设 Str(l,r)Strlr 表示第 ll 杯酒到第 rr 杯酒的 

UOJ #5. 【NOI2014】动物园 扩大KMP

第一次NOI称号. ... 扩展假设知道KMP如果. .. . 就是水题了. ... #5. [NOI2014]动物园 统计提交情况 描写叙述 提交 近日.园长发现动物园中好吃懒做的动物越来越多了.比如企鹅.仅仅会卖萌向游客要吃的. 为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的园长决定开设算法班.让动物们学习算法. 某天,园长给动物们解说KMP算法. 园长:"对于一个字符串S它的长度为L.我们能够在O(L)的时间内求出一个名为next的数组.有谁预习了next数组的含义吗?&