【DP】2018國慶三校聯考
阿新 • • 發佈:2018-12-14
題意:
在N個格子之間,放入D-1個隔板(可以重合),要求每兩個相鄰隔板之間距離不超過M。求方案數。
分析:
儘管D的範圍非常大,但其實很多隔板之間的距離都為0,所以可以考慮距離不為0的隔板的放置方案(即不能重合的方案)。再利用組合數求出在所有隔板中選擇一定數量的方案數。
所以可以設表示用i個格子,放置j各隔板,每兩個之間距離不超過M的方案數。 這可以利用滑窗優化在範圍內算出來。
然後組合數可以直接暴力求,複雜度也是的。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 2010
#define MOD 998244353
using namespace std;
typedef long long ll;
ll dp[MAXN][MAXN];
ll fac[MAXN],ifac[MAXN];
int t;
ll n,m,d;
ll fsp(ll x,ll y){
ll res= 1;
while(y){
if(y&1ll)
res=res*x%MOD;
x=x*x%MOD;
y>>=1ll;
}
return res;
}
ll C(ll x,ll y){
ll sum=1;
for(ll i=x;i>x-y;i--){
ll i1=i%MOD;
sum=sum*i1%MOD;
}
sum=sum*ifac[y]%MOD;
return sum;
}
int main(){
fac[0]=1;
for(ll i=1;i<=2000;i++)
fac[i]=fac[i-1]*i%MOD;
ifac[ 2000]=fsp(fac[2000],MOD-2);
for(ll i=2000;i>=1;i--)
ifac[i-1]=ifac[i]*i%MOD;
while(SF("%lld%lld%lld",&n,&d,&m)!=EOF){
if(n==0&&d==0&&m==0)
break;
m--;
if(m==0){
PF("%d\n",(n==0));
continue;
}
memset(dp,0,sizeof dp);
dp[0][0]=1;
for(int i=1;i<=n;i++){
ll sum=dp[i-1][0];
for(int j=1;j<=n;j++){
dp[i][j]=sum;
sum=(sum+dp[i-1][j])%MOD;
if(j-m>=0)
sum=(sum-dp[i-1][j-m]+MOD)%MOD;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
ans=(ans+C(d,i)*dp[i][n]%MOD)%MOD;
PF("%lld\n",ans);
}
}