1. 程式人生 > >[BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+數位DP)

[BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+數位DP)

pan scanf efi 所有 print 組合數 %d () amp

大組合數取模可以想到Lucas,考慮Lucas的意義,實際上是把數看成P進制計算。

於是問題變成求1~k的所有2333進制數上每一位數的組合數之積。

數位DP,f[i][0/1]表示從高到低第i位,這一位沒卡/卡了限制,的組合數之積,轉移顯然。

WA 8發,都想抽死自己。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
6 7 const int N=3010,P=2333; 8 int T,tot,tot2,C[N][N],S[N][N],a[N],b[N],f[N][2]; 9 ll n,k; 10 11 int main(){ 12 freopen("bzoj4591.in","r",stdin); 13 freopen("bzoj4591.out","w",stdout); 14 C[0][0]=1; rep(i,0,P) S[0][i]=1; 15 rep(i,1,P){ 16 C[i][0]=S[i][0]=1; 17 rep(j,1
,P) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P,S[i][j]=(S[i][j-1]+C[i][j])%P; 18 } 19 for (scanf("%d",&T); T--; ){ 20 scanf("%lld%lld",&n,&k); tot=0; 21 while (n) a[++tot]=n%P,n/=P; 22 rep(i,1,tot) b[i]=k%P,k/=P; 23 f[tot+1][0]=0; f[tot+1][1]=1; 24 for
(int i=tot; i; i--){ 25 f[i][0]=f[i+1][0]*S[a[i]][P-1]%P; 26 if (b[i]) f[i][0]=(f[i][0]+f[i+1][1]*S[a[i]][b[i]-1]%P)%P; 27 f[i][1]=f[i+1][1]*C[a[i]][b[i]]%P; 28 } 29 printf("%d\n",(f[1][0]+f[1][1])%P); 30 } 31 return 0; 32 }

[BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+數位DP)