大意比較簡單,說一下吧:
8個物品,權依次為1~8,第i個物品有cnt[i]([0,1e16])個
給定乙個n([1,1e18]),
從物品中取出若干個,可使得取出物品的總權值為sum,求在sum<=n的條件下,sum的最大值
題解用的技巧很巧妙,取1~8的lcm為l
那麼sum可以化為al+b
對於物品i,可以分為2部分,
一部分從中取出 qi個(qi<=l/i),那麼這部分的總權值小於l
另一部分按照 l/i 個為1捆,分成若干(pi)/捆,我們從中取出的捆數就是[0,pi]
當q[i]從0到l/i-1遍歷時,對於物品i就經歷了所有的情況
具體的:
我們為每個i確定乙個q[i],那麼對於某一種情況,我們記錄下它的所有物品的p[i]的和,那麼
這種情況就可以得到sumq[i]+l*[0,sump[i]]的權值和,這種情況就可以很方便的計算sum最大值了
當然了,不能暴力所有情況,要加一層dp,用dp[i][j]記錄使用前n個物品sumq[i]時的sump[i]
,這樣複雜度就是 8*(l*8)*
最後貼個**
#define clr(a) memset((a),0,sizeof(a))
#define re(i,a) for(int i=0;i
#define re2(i,a) for(int i=1;i<=(int)a;++i)
#define f2(i,a,b) for(int i=a;i>=b;--i)
#define f(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
#define pii pair#define x first
#define y second
/#includetypedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const ll llinf = 0x3f3f3f3f3f3f3f3f;
const int maxn = int(9);
const int l = 840;
ll n;
ll cnt[9];
ll dp[maxn][9 * l];
int main()
}} ll ans(0);
re2(j, 8 * l)if (j <= n && ~dp[8][j])
cout << ans << endl;
} return 0;
}
直銷E化大趨勢
直銷e化是直銷在家創業與網上創業的完美結合 直銷e化使直銷運作如虎添翼,直銷與網際網路的結合也豐富了網上創業的內涵,強化並拓展了網上創業功能,使網際網路功能得以實現最大化。直銷獲得網際網路的有效支援後,在資訊流轉 資料處理 現金支付 物流配送等方面效率大大提高,網上平台與直銷人際網路得到了完美結合。...
Gym 101889E 記憶化搜尋
思維還是太將江華,開始一直想dp,就是這一位餘數固定時取最小的乙個字串,但是字串太大,賦值的時候超時,其實根本沒必要存字串,只要記憶化搜尋,看看 pos res 這個狀態是否能構成就行,這樣的話1000 1000個狀態,穩穩的,然後貪心從小列舉,第乙個可行的一定是最優解。includeusing n...
GYM 101933E(記憶化搜尋)
用每個人的血量作為狀態去搜尋t飛,考慮題解中更好的搜尋方式 每種血量有多少個人作為狀態。這樣會減去很多重複的狀態,因為只要乘一下就得到了所有相同情況的和。雖然我不會算,但是直觀感受起來複雜度比較優秀。include include using namespace std typedef double...