1. 程式人生 > >求 n元一次不定方程 解的個數 的 兩個版本和n種實現方法

求 n元一次不定方程 解的個數 的 兩個版本和n種實現方法

版本1:

 有方程a1*x1+a2*x2+...an*xn=N,給定n(1000=>n>=1)個係數ai(1000>=ai>=0)和N(1000>=N>0),求滿足這個方程的非負整數解(x1,x2...xn)的個數。(結果對10007取模)

實現1:

  構造母函式,(1+x^1+x^2+..x^(N/a1))^^a1*(1+x^1+x^2+..x^(N/a2))^^a2...(1+x^1+..x^(N/an))^^an

^^ai表示從從第一項中取出的項指數乘以ai;

這個函式展開後x^N前面的係數就是方程解的個數。

時間複雜度O(N^2*n);

實現2:

DP,f[N]+=f[N-a[i]] (1<=i<=n)

時間複雜度O(N*n)

版本2:

求方程x1+x2+…...+xn = m滿足xi>=1的解的個數。


輸入由多組資料組成。每組資料輸入一行n和m(1<=n<=300,n<=m<=100000)。

由於方程的解的個數會超過整數範圍,因此輸出的結果對10007求餘

實現1:

由於是上例的特殊情況,令a[i]都=1;

直接套用上例DP時間複雜度為O(m*n),可以接受;

套用母函式時間複雜度為O(m^2*n),速度太慢;

實現2:

用組合數學中的隔板法,直接得結果C(n-1,m-1);

計算C(n-1,m-1)也有兩種解法:

1.C(n,m)=C(n,m-1)+C(n-1,m-1);

  可以遞推,但是m很大消耗記憶體很大,但可以用滾動陣列優化,時間複雜度O(m*n);

2.C(n,m)=m*(m-1)*..(m-n+1)/n!

先令a[1...n]=1..n;a[m-n+1..m]=m-n+1..m;

   可以先將a[1]到a[n]這n個數每個數與a[m-n+1]到a[m]這n個數的最大公約數都約掉,因為C(n,m)是整數,所以

a[1]到a[n]這n個數必然都能完全被約掉,到後面都變為1,最後將a[m-n+1]到a[m]這n個數累乘,乘的同時可以取

模取掉;

時間複雜度O(n^2),跟m無關了,最優!!

附上這種方法的程式碼: