G
考虑先放G
和B
,此时共有\(C_{G+B}^{B}\)种方案。
然后选出\(k\)个G
,在前面放上\(R\),共有\(C_{G}^{k}\)种方案。
最后我们放剩下的\(R-K\)个R
,考虑目前哪些区间内部可以放一段连续的\(R\)。可以发现,单独G的后面,以及B的前后,RG的前后是可以放的,总共是\(B-k+1\)个区间内可以放\(R\)。那么此时就是一个经典的问题——给你\(N\)个桶和\(M\)个球,每个桶可以放任意多个球,球是无标号的,求总方案数。用隔板法发现答案就是\(C_{N-1}^{N+M-1}\)。
最后将这些乘起来就可以得到总方案数了。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
const int maxn=3000005,mod=998244353;
int r,g,b,k;
int fac[maxn];
int qpow(int x,int y) {
if(y==0) return 1;
int ret=qpow(x,y>>1);
ret=1ll*ret*ret%mod;
if(y&1) ret=1ll*ret*x%mod;
return ret;
}
int C(int x,int y) {
return 1ll*fac[x]*qpow(fac[y],mod-2)%mod*qpow(fac[x-y],mod-2)%mod;
}
int D(int x,int y) {
return C(x+y-1,x-1);
}
int main() {
fac[0]=1; for(int i=1;i<maxn;i++) fac[i]=1ll*fac[i-1]*i%mod;
scanf("%d%d%d%d",&r,&g,&b,&k);
printf("%d\n",(int)(1ll*C(g+b,b)*C(g,k)%mod*D(k+b+1,r-k)%mod));
return 0;
}
H
我们发现很多坐标是没用的,准确的说,是只有出发点\((0,0)\)、每个snuke出现的点\((x_{i},y_{i})\)只在\(t_{i}\)时刻是有用的。
那么设\(dp(i)\)表示到了第\(i\)个点,且目前时间是\(t_{i}\),我们得到最大Size的和。
不妨设\(dp(0)\)表示在初始点,并且\(x_{0}=y_{0}=t_{0}=a_{0}=0\)。
那么\(dp(j)\)能转移到\(dp(i)\),当且仅当\(y_{i}\geq y_{j},y_{i}-y_{j}+|x_{i}-x_{j}|\leq t_{i}-t_{j}\)。
转移方程式就是\(dp(i)=\max_{y_{i}\geq y_{j},y_{i}-y_{j}+|x_{i}-x_{j}|\leq t_{i}-t_{j}}(dp(j))+a_{i}\)
标签:AtCoder,return,Beginner,int,ret,266,fac,dp,mod From: https://www.cnblogs.com/Nastia/p/16641835.html