結果
| 問題 | No.3670 Fast Knapsack |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-09-09 13:43:04 |
| 言語 | C++23 (gcc 15.3.0 + boost 1.92.0 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 37 ms / 2,500 ms |
| + 19µs | |
| コード長 | 2,695 bytes |
| 記録 | |
| コンパイル時間 | 3,533 ms |
| コンパイル使用メモリ | 360,128 KB |
| 実行使用メモリ | 6,528 KB |
| 最終ジャッジ日時 | 2026-09-09 13:43:25 |
| 合計ジャッジ時間 | 6,652 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge3_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 25 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, limit) for (long long i = (long long)x; i < (long long)limit; i++)
#define all(x) x.begin(), x.end()
#define el '\n'
#define inp(x) for(auto &i:x)cin>>i
using ll = long long;
using vl = vector<ll>;
const int MAXS = 1 << 18; // 262144 > 200000
template<int SZ>
int solve_bitset(int S, const vector<int>& A){
// Sに必要な最小の2冪サイズまでbitsetを大きくする
if constexpr(SZ < MAXS){
if(S >= SZ){
return solve_bitset<SZ * 2>(S,A);
}
}
bitset<SZ> dp;
dp[0]=1;
int n=A.size();
int i=0;
// A[i] <= S/2 の要素をDP
while(i<n && 2*A[i]<=S){
int j=i;
while(j<n && A[j]==A[i]){
j++;
}
int cnt=j-i;
// 同じ値を二進分解
for(int k=1;cnt>0;k*=2){
int take=min(k,cnt);
ll shift=1LL*A[i]*take;
if(shift<=S){
dp|=dp<<shift;
}
cnt-=take;
}
i=j;
}
// largeを使わない場合
int x=S;
while(!dp[x]){
x--;
}
int ans=x;
// A[i] > S/2 は最大1個しか使えない
while(i<n){
x=min(x,S-A[i]);
while(!dp[x]){
x--;
}
ans=max(ans,x+A[i]);
i++;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--){
int N,S;
cin>>N>>S;
vector<int> A(N);
inp(A);
// Sより大きい要素は絶対使わない
vector<int> B;
for(auto a:A){
if(a<=S){
B.push_back(a);
}
}
sort(all(B));
N=B.size();
ll sum=0;
for(auto a:B){
sum+=a;
}
// 全部入る
if(sum<=S){
cout<<sum<<el;
continue;
}
// Nが小さいなら全探索
if(N<=14){
int ans=0;
vector<int> dp(1<<N);
for(int mask=1;mask<(1<<N);mask++){
int b=__builtin_ctz(mask);
dp[mask]=dp[mask^(1<<b)]+B[b];
if(dp[mask]<=S){
ans=max(ans,dp[mask]);
}
}
cout<<ans<<el;
continue;
}
// gcdで問題を縮小
int g=0;
for(auto a:B){
g=gcd(g,a);
}
if(g>1){
S/=g;
for(auto &a:B){
a/=g;
}
}
int ans=solve_bitset<16>(S,B);
cout<<1LL*ans*g<<el;
}
}