1132E 化大為小,減少無用計算

2021-09-13 22:34:51 字數 1319 閱讀 9752

大意比較簡單,說一下吧:

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...