整数分区(求将整数拆分成任意个数正整数的方法个数)codewars 爆炸求和
依舊是codewars上面的題目,獻上鏈接
codewars 爆炸總和
整數分區
整數n的分區是正整數(不一定是不同的)的無序集合,其加起來為n。這種分區的數量通常表示為p(n)。函數p稱為分區函數,其值列表如下。這從p(0)= 1開始,因為只有一個正整數的集合,其總和為零(即空集合)。
n:p(n)0:1 1:1 //12:2 //1+1 23:3 //1+1+1 1+2+1 34:5 //1+1+1+1 1+1+2 3+1 2+2 45:7 //1+1+1+1+1 1+1+1+2 1+1+3 1+2+2 4+1 2+3 56:11 //1+1+1+1+1+1 1+1+1+1+2 1+1+1+3 1+ 1+2+2 1+1+4 1+2+3 1+5 2+2+2 2+4 3+3 6...數學規律
在寫代碼之前應該先搞懂數學分區的數學規律。
假設將n進行分區,通過規律我們可以知道n各分區中包含n-1的分區加上1,整理之后得出以下規律:
p(n) = p(n-1)
+p(n-2) - p(n-2)中有“+1”的分區方法
+p(n-3) - p(n-3)中有“+1”的分區方法 - p(n-3)中有“+2”的分區方法
…
直到 n-i < i
| 1 | 2 | 3 | 5 | 7 | 11 | 15 | 22 | 30 | 42 |
| +0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| +1 | 0 | 1 | 2 | 3 | 5 | 7 | 11 | 15 | 22 | 30 | p(n-1) |
| +2 | 0 | 0 | 0 | 1 | 1 | 2 | 2 | 4 | 4 | 7 | w[i-1][n-1]-w[i-1][n-2] |
| +3 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | w[i-1][n-1]-w[i-1][n-3] |
| +4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | w[i-1][n-1]-w[i-1][n-4] |
| +5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | w[i-1][n-1]-w[i-1][n-5] |
| … | |||||||||||
| +i | w[i-1][n-1]-w[i-1][n-i] |
則
p(n)=∑w[i][n](0≤i≤(n+1)/2)p(n)=\sum w[i][n](0≤i≤(n+1)/2) p(n)=∑w[i][n](0≤i≤(n+1)/2)
找出規律之后我們就可以寫代碼了
代碼架構
可以看出解決整數分區最重要的兩個函數一個是計算p(n)的求和公式,一個是計算w[n][i]的函數。
//p(n)加和函數 using ull = unsigned long long; ull exp_sum(ull n) {ull num = 0;for (ull i = 0; i <= n/ 2; i++)//當i>n/2,w[n][i]=0{num += cal_w(n, i);}sum_vec.push_back(num); return num; }//w[n][i]的計算函數 ull cal_w(ull n, ull i) {if (n==0||i==0){return 1;}if (i==1){return sum_vec[n - 1];}if (i>n/2){return 0;}return add(n - 1, i - 1) - add(n - i, i - 1); };在頁面上提交的時候發現有超時,那么說明要改數據結構了。
解決函數運行性能,常常用內存換運行時間,也就是將以前計算過得數據存儲出來,方便使用。
加入兩個容器:
代碼更改如下:
//前向聲明ull exp_sum(ull n); ull cal_w(ull n, ull i);//w[n][i]的計算函數 ull cal_w(ull n, ull i) {if (n>=w.size())//如果w中沒有n的相關加和數據,先進行w[n]的計算{w.push_back(vector<ull>(n, 0));w.back()[0] = 1;w.back()[1] = p[n - 1];for (ull i = 2; i <= n / 2; i++){w.back()[i]= cal_w(n - 1, i - 1) - cal_w(n - i, i - 1);}}if (i>=w[n].size()&&i>n/2){return 0;}return w[n][i];//返回w[n][i] };//p(n)加和函數 ull exp_sum(ull n) {while (n>=p.size()){ull num = 0;for (ull i = 0; i <= p.size()/ 2; i++)//p[n]不存在時,先將n以及n以前的所有數據補齊{num += cal_w(p.size(), i);}p.push_back(num);}return p[n]; }然后問題就完美解決了
貼上整數分區的值列表,可以用來調試
整數分區
總結
以上是生活随笔為你收集整理的整数分区(求将整数拆分成任意个数正整数的方法个数)codewars 爆炸求和的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BADI 构建方法(NEW BADI 实
- 下一篇: 位图与矢量图的区别