博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 4583 购物
阅读量:5243 次
发布时间:2019-06-14

本文共 6136 字,大约阅读时间需要 20 分钟。

4583: 购物

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 32  Solved: 16
[][][]

Description

商店出售3种颜色的球,分别为红、绿、蓝。城市里有n个商店,第i个商店在第First_i天开始营业,连续营业Red_
i+Green_i+Blue_i天,每个商店每天只能出售一种颜色的球。每天最多有两个商店同时营业。如果同一天内有两个
商店同时营业,那么这两个商店必须出售相同颜色的球。求不同的出售方案数(对1,000,000,007取模)。两种方
案不同,当且仅当某一天某一个商店出售的球的颜色不同。
 

 

Input

第一行只包含一个整数n,表示商店的个数。
接下来一行有n个数,第i个数表示First_i。
接下来一行有n个数,第i个数表示Red_i。
接下来一行有n个数,第i个数表示Green_i。
接下来一行有n个数,第i个数表示Blue_i。
1≤n≤50
1≤First_i≤500
0≤Red_i, Green_i, Blue_i≤100
0<Red_i + Green_i + Blue_i
First_i + Red_i + Green_i + Blue_i - 1≤500
保证每天最多有两个商店同时营业。
 

 

Output

输出仅包含一个数,表示对1,000,000,007取模后的方案数。
 
 
首先想到dp,f[i][j][k]表示当前第i天,当前的商店已经卖了j个红气球,k个绿气球,这样用蓝气球的个数也是可以知道的。要是有两个区间包含的情况,则可以直接乘组合数转移。相当于被包含的区间强行放满。前后两个区间有交叉同理,因为由当前的状态可以知道接下来交叉的区间要卖红、绿、蓝气球各多少个,所以就可以直接乘组合数转移。其他情况直接转移。
 
感觉代码写的很丑,注意排序前后的顺序不同,不要搞混
1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 #define mod 1000000007 7 #define maxn 120 8 9 typedef long long ll; 10 struct node{ 11 int l,r,rd,bl,gr; 12 bool operator < (node a)const{ 13 return l < a.l; 14 } 15 }dt[maxn],dt2[maxn]; 16 ll f[maxn * 10][maxn][maxn],fac[520],inv[520],ans; 17 int n,m,tag[maxn],tot,cov[maxn * 10],bl[maxn * 10]; 18 int R[maxn],B[maxn],G[maxn],mxR,mxB,mxG,R2[maxn],B2[maxn],G2[maxn]; 19 20 inline ll power(ll x,int y){ 21 ll res = 1; 22 while ( y ){ 23 if ( y & 1 ) res = res * x % mod; 24 y >>= 1; 25 x = x * x % mod; 26 } 27 return res % mod; 28 } 29 void init(){ 30 fac[0] = inv[0] = 1; 31 for (int i = 1 ; i <= 500 ; i++) fac[i] = (ll)i * fac[i - 1] % mod , inv[i] = power(fac[i],mod - 2); 32 for (int i = 1 ; i <= n ; i++) dt[i].rd = R[i] , dt[i].gr = G[i] , dt[i].bl = B[i]; 33 sort(dt + 1,dt + n + 1); 34 for (int i = 1 ; i <= n ; i++) R[i] = dt[i].rd , G[i] = dt[i].gr , B[i] = dt[i].bl; 35 for (int i = 1 ; i <= n ; i++){ 36 for (int j = 1 ; j <= n ; j++){ 37 if ( j == i ) continue; 38 if ( dt[i].l <= dt[j].l && dt[i].r >= dt[j].r ) tag[j] = 1; 39 } 40 } 41 for (int i = 1 ; i <= m ; i++){ 42 for (int j = 1 ; j <= n ; j++){ 43 if ( tag[j] ) continue; 44 if ( dt[j].l <= i && dt[j].r >= i ) cov[i]++; 45 if ( dt[j].l > i ) break; 46 } 47 } 48 for (int i = 1 ; i <= n ; i++){ 49 if ( tag[i] ){ 50 bl[dt[i].l] = i; 51 } 52 } 53 } 54 void Dodp(){ 55 int cur = 1; 56 while ( tag[cur] ) cur++; 57 f[0][0][0] = 1; 58 for (int i = 1 ; i <= m ; i++){ 59 if ( !cov[i] ){ 60 if ( !cov[i - 1] ) f[i][0][0] = f[i - 1][0][0]; 61 else{ 62 for (int j = 0 ; j <= R[cur] ; j++){ 63 for (int k = 0 ; k <= G[cur] ; k++){ 64 f[i][0][0] = (f[i][0][0] + f[i - 1][j][k]) % mod; 65 } 66 } 67 } 68 continue; 69 } 70 if ( i > dt[cur].r ){ 71 for (int j = 0 ; j <= R[cur] ; j++){ 72 for (int k = 0 ; k <= G[cur] ; k++){ 73 f[i][0][0] = (f[i][0][0] + f[i - 1][j][k]) % mod; 74 } 75 } 76 f[i - 1][0][0] = f[i][0][0] , f[i][0][0] = 0; 77 cur++; 78 while ( tag[cur] ) cur++; 79 } 80 if ( cov[i] == 2 ){ 81 int jump = dt[cur].r; 82 for (int j = 0 ; j <= R[cur] ; j++){ 83 for (int k = 0 ; k <= G[cur] && j + k <= i - dt[cur].l ; k++){ 84 int r = R[cur] - j , g = G[cur] - k , b = B[cur] - (i - dt[cur].l - j - k); 85 if ( b < 0 || r + g + b < jump - i + 1 ) continue; 86 f[jump][r][g] = (f[jump][r][g] + fac[jump - i + 1] * inv[r] % mod * inv[g] % mod * inv[b] % mod * f[i - 1][j][k]) % mod; 87 } 88 } 89 cur++ , i = jump; 90 while ( tag[cur] ) cur++; 91 } 92 else{ 93 if ( bl[i] ){ 94 int jump = dt[bl[i]].r; 95 for (int j = 0 ; j <= R[cur] ; j++){ 96 for (int k = 0 ; k <= G[cur] && j + k <= i - dt[cur].l ; k++){ 97 int r = R[bl[i]] + j , g = G[bl[i]] + k , b = B[bl[i]] + (i - dt[cur].l - j - k); 98 if ( r > R[cur] || g > G[cur] || b > B[cur] ) continue; 99 f[jump][r][g] = (f[jump][r][g] + fac[jump - i + 1] * inv[R[bl[i]]] % mod * inv[G[bl[i]]] % mod * inv[B[bl[i]]] % mod * f[i - 1][j][k]) % mod;100 }101 }102 i = jump;103 continue;104 }105 for (int j = 0 ; j <= R[cur] ; j++){106 for (int k = 0 ; k <= G[cur] && j + k <= i - dt[cur].l + 1 ; k++){107 int b = i - dt[cur].l + 1 - j - k;108 if ( b > B[cur] ) continue;109 if ( j > 0 ) f[i][j][k] = (f[i][j][k] + f[i - 1][j - 1][k]) % mod;110 if ( k > 0 ) f[i][j][k] = (f[i][j][k] + f[i - 1][j][k - 1]) % mod;111 if ( b > 0 ) f[i][j][k] = (f[i][j][k] + f[i - 1][j][k]) % mod;112 }113 }114 } 115 }116 }117 int main(){118 // freopen("input.txt","r",stdin);119 scanf("%d",&n);120 for (int i = 1 ; i <= n ; i++) scanf("%d",&dt[i].l);121 for (int i = 1 ; i <= n ; i++) scanf("%d",&R[i]) , mxR = max(mxR,R[i]);122 for (int i = 1 ; i <= n ; i++) scanf("%d",&G[i]) , mxG = max(mxG,G[i]);123 for (int i = 1 ; i <= n ; i++) scanf("%d",&B[i]) , mxB = max(mxB,B[i]);124 for (int i = 1 ; i <= n ; i++) dt[i].r = dt[i].l + R[i] + G[i] + B[i] - 1 , m = max(m,dt[i].r);125 init();126 Dodp();127 for (int j = 0 ; j <= 100 ; j++) 128 for (int k = 0 ; k <= 100 ; k++)129 ans = (ans + f[m][j][k]) % mod;130 printf("%lld\n",ans);131 return 0;132 }

 

转载于:https://www.cnblogs.com/zqq123/p/5501976.html

你可能感兴趣的文章
NOIP2015 运输计划 树上差分+树剖
查看>>
P3950 部落冲突 树链剖分
查看>>
读书汇总贴
查看>>
微信小程序 movable-view组件应用:可拖动悬浮框_返回首页
查看>>
MPT树详解
查看>>
空间分析开源库GEOS
查看>>
RQNOJ八月赛
查看>>
前端各种mate积累
查看>>
jQuery 1.7 发布了
查看>>
Python(软件目录结构规范)
查看>>
Windows多线程入门のCreateThread与_beginthreadex本质区别(转)
查看>>
Nginx配置文件(nginx.conf)配置详解1
查看>>
linux php编译安装
查看>>
name phone email正则表达式
查看>>
「Unity」委托 将方法作为参数传递
查看>>
重置GNOME-TERMINAL
查看>>
redis哨兵集群、docker入门
查看>>
hihoCoder 1233 : Boxes(盒子)
查看>>
oracle中anyData数据类型的使用实例
查看>>
C++对vector里面的元素排序及取任意重叠区间
查看>>