bzoj4583: 购物
挖坑,先发代码已填
我们很容易想到一个7维DP,dp[时间][店A剩余红球][店A剩余绿球][店A剩余蓝球][店B剩余红球][店B剩余绿球][店B剩余蓝球]
然后,首先我们发现,每个时刻一个店的剩余球总数是确定的,于是就可以把其中一个球的状态去掉,于是就变成5维了。
接着,我们尝试不记录其中一个店。
我们发现,如果某一段区间两个店同时开门,那么这段时间内卖掉的球一定是那个较早关门剩余的所有球。(因为较早关门的那个店一定要卖光,然后另一个店就必须跟着卖)
然后这段时间里的方案数,直接可以用组合数算出来。
于是我们就可以直接跳过有2个店开门的时间。
于是我们的DP状态就变成3维的了,空间&&时间都是500*100*100的。
O(1)转移xjb搞一搞就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstring> #include <algorithm> #define ll long long #define N 505 #define P 1000000007 using namespace std; inline int read(){ int ret=0; char ch= getchar (); while (ch< '0' ||ch> '9' ) ch= getchar (); while ( '0' <=ch&&ch<= '9' ){ ret=ret*10-48+ch; ch= getchar (); } return ret; } int fast_pow( int x, int y){ int ret=1; while (y){ if (y&1) ret=(ll)ret*x%P; x=(ll)x*x%P; y=y>>1; } return ret; } struct node{ int l,c0,c1,c2; } a[N]; inline bool operator <( const node &u, const node &v){ return u.l<v.l; } int n; int fact[N],inv[N]; int dp[N][N],f[N][N],sum,now; void jump( int step){ if (!step) return ; if (!sum){now+=step; return ;} memset (f,0, sizeof (f)); for ( int i=0;i<=100;++i) for ( int j=0;j<=100;++j){ int k=sum-i-j; if (k<0||k>100) continue ; if (i) (f[i-1][j]+=dp[i][j])%=P; if (j) (f[i][j-1]+=dp[i][j])%=P; if (k) (f[i][j]+=dp[i][j])%=P; } for ( int i=0;i<=100;++i) for ( int j=0;j<=100;++j) dp[i][j]=f[i][j]; ++now;--sum; jump(step-1); } int main(){ for ( int i=fact[0]=1;i<=500;++i) fact[i]=(ll)fact[i-1]*i%P; for ( int i=0;i<=500;++i) inv[i]=fast_pow(fact[i],P-2); n=read(); for ( int i=1;i<=n;++i) a[i].l=read(); for ( int i=1;i<=n;++i) a[i].c0=read(); for ( int i=1;i<=n;++i) a[i].c1=read(); for ( int i=1;i<=n;++i) a[i].c2=read(); sort(a+1,a+n+1); memset (dp,0, sizeof (dp));dp[0][0]=1; sum=0;now=0; for ( int l=1;l<=n;++l){ jump(a[l].l-now); memset (f,0, sizeof (f)); int k; if (sum<=a[l].c0+a[l].c1+a[l].c2) for ( int i=0;i<=a[l].c0;++i) for ( int j=0;j<=a[l].c1;++j){ k=sum-i-j; if (k<0||k>a[l].c2) continue ; (f[a[l].c0-i][a[l].c1-j]+=(ll)dp[i][j]*fact[sum]%P*inv[i]%P*inv[j]%P*inv[k]%P)%=P; } else for ( int i=a[l].c0;i<=100;++i) for ( int j=a[l].c1;j<=100;++j){ k=sum-i-j; if (k<a[l].c2||k>100) continue ; (f[i-a[l].c0][j-a[l].c1]+=(ll)dp[i][j]*fact[a[l].c0+a[l].c1+a[l].c2]%P*inv[a[l].c0]%P*inv[a[l].c1]%P*inv[a[l].c2]%P)%=P; } for ( int i=0;i<=100;++i) for ( int j=0;j<=100;++j) dp[i][j]=f[i][j]; now+=min(a[l].c0+a[l].c1+a[l].c2,sum); sum= abs (a[l].c0+a[l].c1+a[l].c2-sum); } jump(500); printf ( "%d\n" ,dp[0][0]); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步