1. 程式人生 > 其它 >[NOIP2016 提高組] 組合數問題

[NOIP2016 提高組] 組合數問題

[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(int
j=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; }