CSP/NOIP新賽制內部挑戰賽2 A. 二進位制王國
阿新 • • 發佈:2020-11-27
sub1 (50pts)
設f[i][j] 為用前i種紙幣,還需要總金額為j的方案數
列舉第i個紙幣用了k 張,從f[i−1][j+k∗(2^i)] 轉移
時間複雜度:O(n^2*log n)
sub2 (85pts)
其實就是無限揹包的問題
直接 f[i][j]=f[i−1][j]+f[i][j+(2^i)]
第一維顯然可以壓縮掉
時間複雜度:O(n*log n)
sub3 (95pts)
面值為1 的紙幣考慮完後,j 為奇數的位置就不可能轉移到答案了
面值為2 的紙幣考慮完後,j mod 4 != 0 的位置就不可能轉移到答案了
後面的以此類推
所以轉移有效位置即可
時間複雜度:O(N)
標算
其上一種演算法的空間會炸、
觀察轉移的過程,可以發現程式等價於每次轉移後把座標為奇數的位置刪除,然後把n/ = 2
另外容易發現,使用面值為1 的紙幣時的轉移相當於把陣列的每個位置賦值成1
那麼我們可以手動完成面值為1 的紙幣的轉移,時空常數均除以2
注意哈:面值為0也是一種方案!!
程式碼
#include<bits/stdc++.h> using namespace std; const int maxn=1e8+5; unsigned int f[maxn]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); f[1]=2; int n; scanf("%d",&n); if(!n) { printf("1"); return 0; } n>>=1; for(int i=2;i<=n;i++) f[i]=f[i-1]+f[i>>1]; printf("%u",f[n]); return 0; }