[NOIP2016 提高組] 組合數問題
阿新 • • 發佈:2021-10-02
[NOIP2016 提高組] 組合數問題
難度:普及+/提高
解題思路
此題需要計算大量的排列組合結果,所以選擇楊輝三角來計算排列組合數。
解題難點
下面先編寫了一段楊輝三角和計算個數的程式碼
90pts: O(tnm)楊輝三角
#include <bits/stdc++.h> using namespace std; int k,t,n,m; int f[2500][2500],ans; int main(){ scanf("%d%d",&t,&k); f[0][0]=1; for(int i=1;i<2500;i++) for(intj=1;j<2500;j++){ f[i][j]=f[i-1][j-1]+f[i-1][j]; f[i][j]%=k; } while(t--){ ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n+1;i++) for(int j=1;j<min(i, m+1)+1;j++){ if(f[i][j]==0) ans++; } printf("%d\n",ans); } return 0; }
如果先要拿到100pts,那麼就要對程式碼進行優化。
我們可以在計算楊輝三角時計算字首和。
解題程式碼
100pts: O(tn) 楊輝三角與字首和
#include <bits/stdc++.h> using namespace std; int k,t,n,m; int f[2500][2500],cnt[2500][2500],ans; int main(){ scanf("%d%d",&t,&k); f[0][0]=1; for(int i=1;i<2500;i++) for(int j=1;j<2500;j++){ f[i][j]=f[i-1][j-1]+f[i-1][j]; f[i][j]%=k; cnt[i][j]=cnt[i][j-1]+(!f[i][j]); } while(t--){ ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n+1;i++) ans+=cnt[i][min(i,m+1)]; printf("%d\n",ans); } return 0; }