zoukankan      html  css  js  c++  java
  • 【BZOJ4583】购物(组合计数)

    题意:商店出售3种颜色的球,分别为红、绿、蓝。

    城市里有n个商店,第i个商店在第First_i天开始营业,连续营业Red_i+Green_i+Blue_i天,每个商店每天只能出售一种颜色的球。

    每天最多有两个商店同时营业。如果同一天内有两个商店同时营业,那么这两个商店必须出售相同颜色的球。

    求不同的出售方案数(对1,000,000,007取模)。两种方案不同,当且仅当某一天某一个商店出售的球的颜色不同。

    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
    保证每天最多有两个商店同时营业。
     
    思路:WYZ作业 烦的一比 还是膜了本人的code才做出的
    贴一下他的题解

    我们很容易想到一个7维DP,dp[时间][店A剩余红球][店A剩余绿球][店A剩余蓝球][店B剩余红球][店B剩余绿球][店B剩余蓝球]

    然后,首先我们发现,每个时刻一个店的剩余球总数是确定的,于是就可以把其中一个球的状态去掉,于是就变成5维了。

    接着,我们尝试不记录其中一个店。

    我们发现,如果某一段区间两个店同时开门,那么这段时间内卖掉的球一定是那个较早关门剩余的所有球。(因为较早关门的那个店一定要卖光,然后另一个店就必须跟着卖)

    然后这段时间里的方案数,直接可以用组合数算出来。

    于是我们就可以直接跳过有2个店开门的时间。

    于是我们的DP状态就变成3维的了,空间&&时间都是500*100*100的。

    O(1)转移xjb搞一搞就行了

      1 const mo=1000000007;
      2 var st,r,g,b:array[0..500]of longint;
      3     dp,f:array[0..500,0..500]of int64;
      4     c:array[0..500,-1..500]of int64;
      5     now,sum,i,j,k,n,t:longint;
      6 
      7 procedure swap(var x,y:longint);
      8 var t:longint;
      9 begin
     10  t:=x; x:=y; y:=t;
     11 end;
     12 
     13 procedure qsort(l2,r2:longint);
     14 var i,j,mid:longint;
     15 begin
     16  i:=l2; j:=r2; mid:=st[(l2+r2)>>1];
     17  repeat
     18   while mid>st[i] do inc(i);
     19   while mid<st[j] do dec(j);
     20   if i<=j then
     21   begin
     22    swap(st[i],st[j]);
     23    swap(r[i],r[j]);
     24    swap(g[i],g[j]);
     25    swap(b[i],b[j]);
     26    inc(i); dec(j);
     27   end;
     28  until i>j;
     29  if l2<j then qsort(l2,j);
     30  if i<r2 then qsort(i,r2);
     31 end;
     32 
     33 function clac(x,y,z:longint):int64;
     34 begin
     35  clac:=c[x+y+z,x]*c[y+z,y] mod mo;
     36 end;
     37 
     38 function min(x,y:longint):longint;
     39 begin
     40  if x<y then exit(x);
     41  exit(y);
     42 end;
     43 
     44 procedure solve(step:longint);
     45 var i,j,k:longint;
     46 begin
     47  if step=0 then exit;
     48  if sum=0 then
     49  begin
     50   now:=now+step;
     51   exit;
     52  end;
     53  fillchar(f,sizeof(f),0);
     54  for i:=0 to 100 do
     55   for j:=0 to 100 do
     56   begin
     57    k:=sum-i-j;
     58    if (k<0)or(k>100) then continue;
     59    if i>0 then f[i-1,j]:=(f[i-1,j]+dp[i,j]) mod mo;
     60    if j>0 then f[i,j-1]:=(f[i,j-1]+dp[i,j]) mod mo;
     61    if k>0 then f[i,j]:=(f[i,j]+dp[i,j]) mod mo;
     62   end;
     63  for i:=0 to 100 do
     64   for j:=0 to 100 do dp[i,j]:=f[i,j];
     65  inc(now); dec(sum);
     66  solve(step-1);
     67 end;
     68 
     69 begin
     70  assign(input,'bzoj4583.in'); reset(input);
     71  assign(output,'bzoj4583.out'); rewrite(output);
     72  readln(n);
     73  for i:=1 to n do read(st[i]);
     74  for i:=1 to n do read(r[i]);
     75  for i:=1 to n do read(g[i]);
     76  for i:=1 to n do read(b[i]);
     77  c[0,0]:=1;
     78  for i:=1 to 500 do
     79   for j:=0 to i do c[i,j]:=(c[i-1,j-1]+c[i-1,j]) mod mo;
     80  qsort(1,n); dp[0,0]:=1;
     81  for t:=1 to n do
     82  begin
     83   solve(st[t]-now);
     84   fillchar(f,sizeof(f),0);
     85   if sum<=r[t]+g[t]+b[t] then
     86   begin
     87    for i:=0 to r[t] do
     88     for j:=0 to g[t] do
     89     begin
     90      k:=sum-i-j;
     91      if (k<0)or(k>b[t]) then continue;
     92      f[r[t]-i,g[t]-j]:=(f[r[t]-i,g[t]-j]+dp[i,j]*clac(i,j,k)) mod mo;
     93     end;
     94   end
     95    else
     96    begin
     97     for i:=r[t] to 100 do
     98      for j:=g[t] to 100 do
     99      begin
    100       k:=sum-i-j;
    101       if (k<b[t])or(k>100) then continue;
    102       f[i-r[t],j-g[t]]:=(f[i-r[t],j-g[t]]+dp[i,j]*clac(r[t],g[t],b[t])) mod mo;
    103      end;
    104    end;
    105   for i:=0 to 100 do
    106    for j:=0 to 100 do dp[i,j]:=f[i,j];
    107   now:=now+min(sum,r[t]+g[t]+b[t]);
    108   sum:=abs(r[t]+g[t]+b[t]-sum);
    109  end;
    110  solve(500);
    111  writeln(dp[0,0]);
    112  close(input);
    113  close(output);
    114 end.
     

     

  • 相关阅读:
    函数
    python操作文件
    POJ-2689-Prime Distance(素数区间筛法)
    POJ-2891-Strange Way to Express Integers(线性同余方程组)
    POJ-2142-The Balance
    POJ-1061-青蛙的约会(扩展欧几里得)
    Educational Codeforces Round 75 (Rated for Div. 2) D. Salary Changing
    Educational Codeforces Round 75 (Rated for Div. 2) C. Minimize The Integer
    Educational Codeforces Round 75 (Rated for Div. 2) B. Binary Palindromes
    Educational Codeforces Round 75 (Rated for Div. 2) A. Broken Keyboard
  • 原文地址:https://www.cnblogs.com/myx12345/p/6554717.html
Copyright © 2011-2022 走看看