求 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無關了,最優!!
附上這種方法的程式碼: