[數位DP 多重揹包計數] BZOJ5003. 與鏈
阿新 • • 發佈:2019-02-03
每一位二進位制分開考慮
那麼在一個合法的序列中,一定是前面幾個數當前二進位制位是1,其他都是0
數位DP,每一位的1最多出現k次,這就是一個多重揹包
多重揹包轉移用字首和優化就好了
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100010,P=1e9+9;
int n,K,f[20][N][2];
int tmp[N];
inline void add(int &x,int y){
(x+=y)%=P;
}
int main(){
scanf("%d%d",&K,&n);
f[17 ][0][1]=1;
for(int i=17;i;i--){
int t=1<<i-1;
for(int k=0;k<=1;k++){
if(k==1 && !((n>>i-1)&1)){
for(int j=0;j<=n;j++) add(f[i-1][j][k],f[i][j][k]);
continue;
}
for(int j=0;j<=n;j++) add(f[i-1][j][0],f[i][j][k]);
for(int j=0;j<=n;j++)
tmp[j]=(f[i][j][k]+(j-t<0?0:tmp[j-t]))%P;
for(int j=t;j<=n;j++){
int nxt=(k==1 && ((n>>i-1)&1));
add(f[i-1][j][nxt],(tmp[j-t]-(j-1LL*t*(K+1)<0?0:tmp[j-t*(K+1)]))%P);
}
}
}
int ans=(f[0][n][0]+f[0][n][1])%P;
cout<<(ans+P)%P<<endl;
return 0;
}