• 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 }
  • 相关阅读:
    linux 下的mysql
    linux历史命令,索引与键
    root用户删除恢复,mysql二进制及源码安装,mysql关闭,重启,开启命令
    pip3换源,grep,sed ,awk 三剑客,通配符,linux运行django项目
    软硬连接,find命令date命令,du大文件, tar zip压缩解压命令,
    微服务 架构 php+go
    go 优秀 博客文档
    go-001[常用命令]
    go 0000
    web 安全:
  • 原文地址:https://www.cnblogs.com/zqq123/p/5501976.html
Copyright © 2020-2023  润新知