bzoj 4583 购物

4583: 购物

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

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<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  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
",ans);
131     return 0;
132 }
原文地址:https://www.cnblogs.com/zqq123/p/5501976.html