Problem:
500-yen Saving
"500-yen Saving" is one of Japanese famous methods to save money. The
method is quite simple; whenever you receive a 500-yen coin in your
change of shopping, put the coin to your 500-yen saving box.
Typically, you will find more than one million yen in your saving box
in ten years.
Some Japanese people are addicted to the 500-yen saving. They try
their best to collect 500-yen coins efficiently by using 1000-yen bills
and some coins effectively in their purchasing. For example, you will give
1320 yen (one 1000-yen bill, three 100-yen coins and two 10-yen coins)
to pay 817 yen, to receive one 500-yen coin (and three 1-yen coins)
in the change.
A friend of yours is one of these 500-yen saving addicts.  He is
planning a sightseeing trip and wants to visit a number of souvenir
shops along his way.  He will visit souvenir shops one by one
according to the trip plan. Every souvenir shop sells only one kind of
souvenir goods, and he has the complete list of their prices.  He
wants to collect as many 500-yen coins as possible through buying
at most one souvenir from a shop.  On his departure,
he will start with sufficiently many 1000-yen bills and no coins at
all.  The order of shops to visit cannot be changed.  As far as he can
collect the same number of 500-yen coins, he wants to cut his expenses
as much as possible.
Let's say that he is visiting shops with their souvenir prices of 800
yen, 700 yen, 1600 yen, and 600 yen, in this order.  He can collect at
most two 500-yen coins spending 2900 yen, the least expenses to collect
two 500-yen coins, in this case.  After skipping the first shop, the
way of spending 700-yen at the second shop is by handing over a
1000-yen bill and receiving three 100-yen coins.  In the next shop,
handing over one of these 100-yen coins and two 1000-yen bills for
buying a 1600-yen souvenir will make him receive one 500-yen coin. In
almost the same way, he can obtain another 500-yen coin at the last
shop.  He can also collect two 500-yen coins buying at the first shop,
but his total expenditure will be at least 3000 yen because he needs
to buy both the 1600-yen and 600-yen souvenirs in this case.
You are asked to make a program to help his collecting 500-yen coins
during the trip.  Receiving souvenirs' prices listed in the order
of visiting the shops, your program is to find the maximum number of
500-yen coins that he can collect during his trip, and the minimum
expenses needed for that number of 500-yen coins.
For shopping, he can use an arbitrary number of 1-yen, 5-yen, 10-yen,
50-yen, and 100-yen coins he has, and arbitrarily many 1000-yen bills.
The shop always returns the exact change, i.e., the difference between
the amount he hands over and the price of the souvenir.  The shop has
sufficient stock of coins and the change is always composed of the
smallest possible number of 1-yen, 5-yen, 10-yen, 50-yen, 100-yen, and
500-yen coins and 1000-yen bills.  He may use more money than the
price of the souvenir, eve
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef int ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1 << 30;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;
 
void solve(int n) {
  vll x(n);cin >> x;

  // dp[i][j][k] := iまでみてj枚500円玉があり、k円小銭があるときの支払う総額の最小値
  // dp[i][k] := (500enndama no maisuu, tukattakingaku)
  ll lim = 500 * 100 + 10;
  vector<vpll>dp(n+1,vector<pll>(lim,{0,INF}));
  dp[0][0] = {0,0};
  auto cng = [&](pll &a, pll b){
    if(a.first < b.first){
      a = b;
    }else if(a.first == b.first && a.second > b.second)a = b;
  };  
  rep(i,n){
    // vector<unordered_map<ll,ll>>ndp(n+1);
    rrep(j,lim-1,0)if(dp[i][j] != pll{0,INF}){
      // if(j+n-i-1 <jmax)continue;
        auto [num,val] = dp[i][j];
        cng(dp[i+1][j],dp[i][j]);
        //500円ちょうどを作り出す
        ll rem = (x[i] + 500) % 1000;
        if(rem <= j){
          ll nk = j -rem;
          cng(dp[i+1][nk],pll{num+1,val + x[i]});
        }
        //1000の倍数で払う
        if(x[i] % 1000 != 0){
          ll payval = lceil(x[i],1000) * 1000;
          if(x[i] % 1000 <= 500){
            //500円もらえる
            ll nk = j + payval - x[i] -500;
            // if(500 * (n-i+1) < nk)continue;
            cng(dp[i+1][nk],pll{num+1,val+x[i]});
          }else{
            //500円もらえない
            ll nk = j + payval -x[i];
            // if(500 * (n-i+1) < nk)continue;
            cng(dp[i+1][nk],pll{num,val+x[i]});
          }
        }
      }
    }
    /*
    debug
    
    */
  //  cout <<"i :" << i << endl; 
  //   repn(j,n){
  //     cout <<"j :" <<  j << endl;
  //     if(!dp[j].empty()){
  //        for(auto &[k,cost]:dp[j]){
  //         cout << k  << " " << cost << endl;
  //        }
  //     }
  //   }
  //   cout << endl;
  ll num = 0;
  ll best = INF;
  rep(i,lim){
    if(chmax(num,dp[n][i].first)){
      best = dp[n][i].second;
    }else if(num == dp[n][i].first){
      chmin(best,dp[n][i].second);
    }
  }
  cout << num << " " << best << endl;
  

}


int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while (true) {
    int n; cin >> n;
    if (n == 0) break;
    solve(n);
  }
  
}
accuracy: 1
time_ms: 360
memory_kb: 43392
final_rank: 9

code_snippet: #include <bits/stdc++.h>
      
#define FOR(i,a,b) for( ll i = (a); i < (ll)(b); i++ )
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define ALL(x) (x).begin(),(x).end()
#define SORT(x) sort( (x).begin(),(x).end() )
#define REVERSE(x) reverse( (x).begin(),(x).end() )
#define UNIQUE(x) (x).erase( unique( ALL( (x) ) ) , (x).end() )
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())
#define SHOW(x) cout << #x << " = " << x << endl
#define SHOWA(x,n) for( int yui = 0; yui < n; yui++ ){ cout << x[yui] << " "; } cout << endl

#define pb emplace_back
#define fi first
#define se second

using namespace std;

typedef long double ld;
typedef long long int ll;
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<ld> vd;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<vpl> gr;
typedef vector<vl> ml;
typedef vector<vd> md;
typedef vector<vi> mi;
     
const ll INF = (ll)1e9 + 10;
const ll INFLL = (ll)1e18 + 10;
const ld EPS = 1e-12;
const ll MOD = 1e9+7;
     
template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> inline T sq( T a ){ return a * a; }

ll in(){ long long int x; scanf( "%lld" , &x ); return x; }
char yuyushiki[1000010]; string stin(){ scanf( "%s" , yuyushiki ); return yuyushiki; }

// head

const int N = 50010;

pi dp[128][N];

int n;
int p[128];

int main(){

  while( 1 ){
    n = in();
    if( n == 0 ){
      break;
    }
    
    REP( i , n ){
      p[i] = in();
    }

    REP( i , 128 ){
      REP( j , N ){
        dp[i][j] = pi( -INF, INF );
      }
    }
    
    dp[0][0] = pi( 0 , 0 );

    REP( i , n ){
      REP( k , N ){
        if( dp[i][k] == pi( -INF, INF ) ){
          continue;
        }

        // get
        int nec = 0;
        int get = 500 - ( p[i] % 1000 );
        if( p[i] % 1000 == 0 ){
          nec = 500;
          get = 0;
        } else if( p[i] % 1000 > 500 ){
          nec = p[i] % 1000 - 500;
          get = 0;
        }
        if( nec <= k ){
          int nk = k-nec+get;
          if( 0 <= nk && nk < N ){
            chmax( dp[i+1][nk], pi( dp[i][k].fi + 1, dp[i][k].se - p[i] ) );
          }
        }
        
        // not get
        get = 1000 - ( p[i] % 1000 );
        if( p[i] % 1000 == 0 ){
          get = 0;
        }
        if( k+get < N ){
          chmax( dp[i+1][k+get], pi( dp[i][k].fi, dp[i][k].se - p[i] ) );
        }
        chmax( dp[i+1][k], dp[i][k] );
      }
    }

    pi res = pi( -INF, INF );
    REP( j , N ){
      chmax( res , dp[n][j] );
    }

    printf( "%d %d\n" , res.fi, -res.se );
  }

  return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 53456
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)

template<typename T>
inline void chmax(T& a, T b) { a = max(a, b); }

inline void solve() {
  int n;
  cin >> n;
  if (n == 0) exit(0);
  vector<int> a(n);
  rep(i, n) cin >> a[i];
  constexpr int m = 50000;
  vector dp(n + 1, vector<pair<int, int>>(m, make_pair(-1e9, -1e9)));
  dp[0][0] = { 0, 0 };
  rep(i, n) {
    for (int j = 0; j < m; ++j) {
      if (dp[i][j].first < 0) continue;
      // つかわない
      chmax(dp[i + 1][j], dp[i][j]);
      // つかう
      if (0 < a[i] % 1000 && a[i] % 1000 <= 500) {
        int rem = 500 - a[i] % 1000;
        if (j + rem < m) chmax(dp[i + 1][j + rem], make_pair(dp[i][j].first + 1, dp[i][j].second - a[i]));
      }
      else {
        int use = ((a[i] % 1000 - 500) + 1000) % 1000;
        // ふつうにはらう
        {
          int rem = (1000 - a[i] % 1000) % 1000;
          if (j + rem < m) chmax(dp[i + 1][j + rem], make_pair(dp[i][j].first, dp[i][j].second - a[i]));
        }
        // おつりつかう
        if (j >= use) {
          if (j - use < m) chmax(dp[i + 1][j - use], make_pair(dp[i][j].first + 1, dp[i][j].second - a[i]));
        }
      }
    }
  }
  pair<int, int> ans = { -1e9, -1e9 };
  rep(j, m) chmax(ans, dp[n][j]);
  cout << ans.first << ' ' << -ans.second << '\n';
}

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  while (true) solve();
  // solve();
}
accuracy: 1
time_ms: 350
memory_kb: 43392
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define fi first
#define se second
#define rep(i,s,n) for (int i = (s); i < (n); ++i)
#define rrep(i,n,g) for (int i = (n)-1; i >= (g); --i)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define len(x) (int)(x).size()
#define dup(x,y) (((x)+(y)-1)/(y))
#define pb push_back
#define eb emplace_back
#define Field(T) vector<vector<T>>
using namespace std;
using ll = long long;
using ull = unsigned long long;
template<typename T> using pq = priority_queue<T,vector<T>,greater<T>>;
using P = pair<int,int>;
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}

static constexpr int inf = 1000000000;

bool solve() {
  int n;
  cin >> n;
  if (n == 0) return 1;
  vector<int> p(n);
  rep(i,0,n) cin >> p[i];
  vector<vector<P>> dp(n+1, vector<P>(50001, {0, inf}));
  dp[0][0].se = 0;
  rep(i,0,n) rep(j,0,50001) {
    if (dp[i][j].se == inf) continue;
    chmin(dp[i+1][j], dp[i][j]);
    int x = 1000*dup(p[i], 1000) - p[i];
    if (x >= 500) {
      P np = dp[i][j];
      np.fi -= 1, np.se += p[i];
      chmin(dp[i+1][j+x-500], np);
    } else {
      if (500-x > j) {
        P np = dp[i][j];
        np.se += p[i];
        chmin(dp[i+1][j+x], np);
      } else {
        P np = dp[i][j];
        np.fi -= 1, np.se += p[i];
        chmin(dp[i+1][j+x-500], np);
      }
    }
  }
  P ans = {0, inf};
  rep(j,0,50001) chmin(ans, dp[n][j]);
  cout << -ans.fi << " " << ans.se << endl;
  return 0;
}

int main() {
  while(!solve());
  return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 42976
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#include <unordered_map>
#include <stdlib.h>
using namespace std;
#define rep(i, a, n) for(ll i = a; i < n; i++)
#define rrep(i, a, n) for(ll i = a; i >= n; i--)
#define ll int
#define pii pair<int, int>
#define pll pair<ll, ll>
#define all(x) (x).begin(), (x).end()
//constexpr ll MOD = 1000000007;
constexpr ll MOD = 998244353;
constexpr int IINF = 1001001001;
// constexpr ll INF = 1LL<<60;
template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

ll gcd(ll a, ll b){
    if(a%b == 0){
      return b;
    }else{
      return gcd(b, a%b);
    }
}

ll lcm(ll a, ll b){
    return a*b / gcd(a, b);
}

ll powMod(ll x, ll n) {
    if (n == 0) return 1 % MOD;
    ll val = powMod(x, n / 2);
    val *= val;
    val %= MOD;
    if (n % 2 == 1) val *= x;
    return val % MOD;
}

int main() {
    while(true){
        ll n; cin >> n;
        if(n == 0) break;
        vector<ll> p(n), pm(n);
        rep(i,0,n) cin >> p[i], pm[i] = p[i]%1000;
        vector<pll> dp(50000, {0,-IINF});
        dp[0] = {0,0};
        rep(i,0,n){
            vector<pll> ndp(50000, {0,-IINF});
            rep(j,0,50000){
                if(dp[j] == make_pair(0,-IINF)) continue;
                auto [x, y] = dp[j];
                // cout << "ok " << i << " " << j << " " << x << " " << y << endl;
                chmax(ndp[j], dp[j]);
                if(pm[i] > 500){
                    chmax(ndp[j+1000-pm[i]], make_pair(x, y-p[i]));
                    if(j >= -500+pm[i]) chmax(ndp[j+500-pm[i]], make_pair(x+1, y-p[i]));
                }else if(pm[i] > 0){
                    chmax(ndp[j+500-pm[i]], make_pair(x+1, y-p[i]));
                }else{
                    if(j >= 500) chmax(ndp[j-500], make_pair(x+1, y-p[i]));
                }
            }
            swap(dp, ndp);
            pll ans = {0,0};
            rep(j,0,50000){
                chmax(ans, dp[j]);
            }
            // cout << i << " " << ans.first << " " << -ans.second << endl;
        }
        pll ans = {0, 0};
        rep(i,0,50000){
            chmax(ans, dp[i]);
        }
        cout << ans.first << " " << -ans.second << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 4564
final_rank: 4

code_snippet: //#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n) for (ll i=0;i<(ll)n;i++)
#define rrep(i,n) for (ll i=n-1;i>=(ll)0;i--)
#define loop(i,m,n) for(ll i=m;i<=(ll)n;i++)
#define rloop(i,m,n) for(ll i=m;i>=(ll)n;i--)
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vpdbg(a) rep(ii,a.size()){cout<<"{"<<a[ii].first<<","<<a[ii].second<<"} ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define setdbg(a) for(const auto & ii:a){cout<<ii<<" ";}cout<<endl;
#define inf 1e9
#define mod 998244353LL
//#define mod 1000000007LL
#define eps 0.000000001
random_device rnd;// 非決定的な乱数生成器
mt19937 mt(rnd());// メルセンヌ・ツイスタの32ビット版、引数は初期シード

//#include<boost/multiprecision/cpp_int.hpp>
//#define bbi boost::multiprecision::cpp_int
//#include<atcoder/lazysegtree>


//整数同士の累乗の計算をする。
ll power(ll A, ll B) {
	ll result = 1;
	for (ll i=0;i<B;i++){
		result *= A;
	}
	return result;
}

// nのk乗をmodで割った余りを計算
ll power_mod(ll n, ll k){
	long long result = 1;
	while (k > 0){
		if ((k&1) ==1)result=(result*n)%mod;
		n=n*n%mod;
		k >>= 1;
	}
	return result;
}


//受け取った2次元文字の外側に、文字pをコーティングする。
vector<string> pad(vector<string> &s,char p){
	ll h=s.size();
	ll w=s[0].size();
	vector<string> res(h+2,string(w+2,p));
	rep(i,h)rep(j,w)res[i+1][j+1]=s[i][j];
	return res;
}

// Union-Find
struct UnionFind {
	vector<int> par, siz;
	UnionFind(int n) : par(n, -1) , siz(n, 1) { }
	// 根を求める
	int root(int x) {
		if (par[x] == -1) return x;
		else return par[x] = root(par[x]);
	}
	// x と y が同じグループに属するかどうか (根が一致するかどうか)
	bool issame(int x, int y) {
		return root(x) == root(y);
	}
	// x を含むグループと y を含むグループとを併合する
	bool unite(int x, int y) {
		x = root(x), y = root(y);
		if (x == y) return false; 
		if (siz[x] < siz[y]) swap(x, y);
		par[y] = x;
		siz[x] += siz[y];
		return true;
	}
	// x を含むグループのサイズ
	int size(int x) {
		return siz[root(x)];
	}
};


//グリッド問題等用
vl dx={1,0,-1,0};
vl dy={0,1,0,-1};


ll solve(){
	ll n;
	cin>>n;
	if(n==0){return 1;}

	//dp[i][j] = i番目までの商品を買って、j円の小銭を所持している時の{個数,使用金額}
	vector<vector<pair<ll,ll>>> dp(n+1,vector<pair<ll,ll>>(n*500+1,{inf,inf}));
	
	dp[0][0]={0,0};

	rep(i,n){
		ll a;
		cin>>a;

		//そもそも買わない場合
		dp[i+1]=dp[i];
		
		//必ず買う場合
		if(1<=a%1000&&a%1000<=500){
			ll tmp = 1000-500-(a%1000);
			rep(j,i*500+1){
				dp[i+1][j+tmp] = min(make_pair(dp[i][j].first-1,dp[i][j].second+a),dp[i+1][j+tmp]);
			}
			continue;
		}

		
		//買う場合
		rep(j,i*500+1){
			ll p=a%1000;
			if(p==0)p+=1000;
			ll tmp = 1000-500-p;
			if(0<=tmp+j){
				pair<ll,ll> pr={dp[i][j].first-1,dp[i][j].second+a};
				dp[i+1][tmp+j]=min(pr,dp[i+1][tmp+j]);
			}else{
				pair<ll,ll> pr={dp[i][j].first,dp[i][j].second+a};
				dp[i+1][1000-p+j]=min(pr,dp[i+1][1000-p+j]);
			}
		}
	}

	pair<ll,ll> ans={inf,inf};
	
	loop(i,0,n*500){
		ans=min(ans,dp[n][i]);
	}

	cout<<-ans.first<<" "<<ans.second<<endl;
	return 0;
}

//メイン
int main(){
	while(solve()==0);
	return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 83024
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef int ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1 << 30;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;
 
void solve(int n) {
  vll x(n);cin >> x;

  // dp[i][j][k] := iまでみてj枚500円玉があり、k円小銭があるときの支払う総額の最小値
  // dp[i][k] := (500enndama no maisuu, tukattakingaku)
  ll lim = 500 * 100 + 10;
  vector<vpll>dp(n+1,vector<pll>(lim,{0,INF}));
  dp[0][0] = {0,0};
  auto cng = [&](pll &a, pll b){
    if(a.first < b.first){
      a = b;
    }else if(a.first == b.first && a.second > b.second)a = b;
  };  
  rep(i,n){
    // vector<unordered_map<ll,ll>>ndp(n+1);
    rrep(j,lim-1,0)if(dp[i][j] != pll{0,INF}){
      // if(j+n-i-1 <jmax)continue;
        auto [num,val] = dp[i][j];
        cng(dp[i+1][j],dp[i][j]);
        //500円ちょうどを作り出す
        ll rem = (x[i] + 500) % 1000;
        if(rem <= j){
          ll nk = j -rem;
          cng(dp[i+1][nk],pll{num+1,val + x[i]});
        }
        //1000の倍数で払う
        if(x[i] % 1000 != 0){
          ll payval = lceil(x[i],1000) * 1000;
          if(x[i] % 1000 <= 500){
            //500円もらえる
            ll nk = j + payval - x[i] -500;
            // if(500 * (n-i+1) < nk)continue;
            cng(dp[i+1][nk],pll{num+1,val+x[i]});
          }else{
            //500円もらえない
            ll nk = j + payval -x[i];
            // if(500 * (n-i+1) < nk)continue;
            cng(dp[i+1][nk],pll{num,val+x[i]});
          }
        }
      }
    }
    /*
    debug
    
    */
  //  cout <<"i :" << i << endl; 
  //   repn(j,n){
  //     cout <<"j :" <<  j << endl;
  //     if(!dp[j].empty()){
  //        for(auto &[k,cost]:dp[j]){
  //         cout << k  << " " << cost << endl;
  //        }
  //     }
  //   }
  //   cout << endl;
  ll num = 0;
  ll best = INF;
  rep(i,lim){
    if(chmax(num,dp[n][i].first)){
      best = dp[n][i].second;
    }else if(num == dp[n][i].first){
      chmin(best,dp[n][i].second);
    }
  }
  cout << num << " " << best << endl;
  

}


int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while (true) {
    int n; cin >> n;
    if (n == 0) break;
    solve(n);
  }
  
}
accuracy: 1
time_ms: 360
memory_kb: 43392
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int M = 5000;
int main(){
    while (true){
        int n;
        cin >> n;
        if (n == 0){
            return 0;
        }
        vector<vector<int>> dp(n + 1, vector<int>(M, 1e9));
        dp[0][0] = 0;
        for (int i = 0; i < n; i++){
            int p;
            cin >> p;
            for (int j = n - 1; j >= 0; j--){
                for (int k = M - 1; k >= 0; k--){
                    int c = p % 1000;
                    if (c <= 500){
                        if (0 < c and k + (500 - c) < M){
                            dp[j + 1][k + (500 - c)] = min(dp[j + 1][k + (500 - c)], dp[j][k] + p);
                        }
                        if (k >= c + 500){
                            dp[j + 1][k - (c + 500)] = min(dp[j + 1][k - (c + 500)], dp[j][k] + p);
                        }
                    } else {
                        if (k + (1000 - c) < M){
                            dp[j][k + (1000 - c)] = min(dp[j][k + (1000 - c)], dp[j][k] + p);
                        }
                        if (k >= (c - 500)){
                            dp[j + 1][k - (c - 500)] = min(dp[j + 1][k - (c - 500)], dp[j][k] + p);
                        }
                    }
                }
            }
        }
        for (int i = n; i >= 0; i--){
            int m = *min_element(dp[i].begin(), dp[i].end());
            if (m != 1e9){
                cout << i << " " << m << endl;
                break;
            }
        }
    }
}
accuracy: 1
time_ms: 3050
memory_kb: 5204
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#include <atcoder/all>

using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using bint = __int128_t;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for (ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define TT template <typename T>
TT using vec = vector<T>;
TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;
template <class T> bool chmin(T &x, T y) {
    return x > y ? (x = y, true) : false;
}
template <class T> bool chmax(T &x, T y) {
    return x < y ? (x = y, true) : false;
}
struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

std::ostream &operator<<(std::ostream &dest, __int128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[128];
        char *d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}

__int128 parse(string &s) {
    __int128 ret = 0;
    for (size_t i = 0; i < s.length(); i++)
        if ('0' <= s[i] && s[i] <= '9')
            ret = 10 * ret + s[i] - '0';
    return ret;
}

std::istream &operator>>(std::istream &dest, __int128_t &value) {
    string s;
    dest >> s;
    value = parse(s);
    return dest;
}

const ll inf = LLONG_MAX / 4;
int main() {
    ll n;
    while (1) {
        cin >> n;
        if (n == 0)
            return 0;
        vector<ll> P(n);
        rep(i, 0, n) cin >> P[i];

        const ll M = 550 * n;

        auto change = [&](pll &a, pll b) {
            if (a.first < b.first) {
                a = b;
                return true;
            } else if (a.first == b.first) {
                return chmin(a.second, b.second);
            }
            return false;
        };

        auto oturi = [&](ll x) {
            x %= 1000;
            if (x == 0)
                return 0LL;
            return 1000LL - x;
        };

        vector<pll> dp(M, {-inf, inf});
        dp[0] = {0, 0};

        rep(i, 0, n) {
            auto pre = dp;

            // 買う場合
            rep(one, 0, M) if (pre[one] != pll{-inf, inf}) {
                // 1000円pay
                if (oturi(P[i]) + one < M)
                    change(dp[oturi(P[i]) + one],
                           {pre[one].first, pre[one].second + P[i]});
                // 500円玉get
                if (P[i] % 1000 == 0) {
                    if (one >= 500) {
                        change(dp[one - 500],
                               {pre[one].first + 1, pre[one].second + P[i]});
                    }
                } else {
                    if (P[i] % 1000 <= 500) {
                        if (oturi(P[i]) + one - 500 < M)
                            change(
                                dp[oturi(P[i]) + one - 500],
                                {pre[one].first + 1, pre[one].second + P[i]});
                    } else {
                        ll use = P[i] % 1000 - 500;
                        if (one >= use)
                            change(dp[one - use], {pre[one].first + 1,
                                                   pre[one].second + P[i]});
                    }
                }
            }
        }

        pll ans(-inf, inf);
        rep(one, 0, M) {
            change(ans, dp[one]);
        }
        cout << ans.first << " " << ans.second << endl;
    }
}
accuracy: 1
time_ms: 220
memory_kb: 5120
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

constexpr int MAX_MONEY = 50000;
constexpr int INF       = 1e9;

int main() {
    while (true) {
        int N;
        cin >> N;
        if (N == 0) {
            break;
        }

        vector<int> prices(N);
        for (int i = 0; i < N; ++i) {
            cin >> prices[i];
        }

        vector<pair<int, int>> dp(MAX_MONEY + 1, {-1, INF});
        dp[0] = {0, 0};

        for (int idx = 0; idx < N; ++idx) {
            int price                      = prices[idx];
            vector<pair<int, int>> next_dp = dp;

            for (int m = 0; m <= MAX_MONEY; ++m) {
                if (dp[m].first == -1) {
                    continue;
                }

                auto [c, s] = dp[m];
                if (next_dp[m].first < c || (next_dp[m].first == c && next_dp[m].second > s)) {
                    next_dp[m] = {c, s};
                }

                int r      = price % 1000;
                int need   = min(r, m);
                int pay    = price - need;
                int change = (1000 - (pay % 1000)) % 1000;
                int new_m  = m - need + change;

                if (change < 500 && new_m <= MAX_MONEY) {
                    if (next_dp[new_m].first < c || (next_dp[new_m].first == c && next_dp[new_m].second > s + price)) {
                        next_dp[new_m] = {c, s + price};
                    }
                }

                if (r == 0 && m >= 500) {
                    int nm = m - 500;
                    if (nm >= 0 && nm <= MAX_MONEY) {
                        if (next_dp[nm].first < c + 1 || (next_dp[nm].first == c + 1 && next_dp[nm].second > s + price)) {
                            next_dp[nm] = {c + 1, s + price};
                        }
                    }
                } else if (r > 0 && r <= 500) {
                    int nm = m + 500 - r;
                    if (nm <= MAX_MONEY) {
                        if (next_dp[nm].first < c + 1 || (next_dp[nm].first == c + 1 && next_dp[nm].second > s + price)) {
                            next_dp[nm] = {c + 1, s + price};
                        }
                    }
                } else if (r > 500 && m >= r - 500) {
                    int nm = m - (r - 500);
                    if (nm >= 0 && nm <= MAX_MONEY) {
                        if (next_dp[nm].first < c + 1 || (next_dp[nm].first == c + 1 && next_dp[nm].second > s + price)) {
                            next_dp[nm] = {c + 1, s + price};
                        }
                    }
                }
            }
            dp.swap(next_dp);
        }

        int max_c = -1, min_s = INF;
        for (int m = 0; m <= MAX_MONEY; ++m) {
            if (dp[m].first > max_c || (dp[m].first == max_c && dp[m].second < min_s)) {
                max_c = dp[m].first;
                min_s = dp[m].second;
            }
        }
        cout << max_c << " " << min_s << endl;
    }
}
accuracy: 1
time_ms: 110
memory_kb: 4568
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(...) std::begin(__VA_ARGS__), std::end(__VA_ARGS__)
#define rall(...) std::rbegin(__VA_ARGS__), std::rend(__VA_ARGS__)
#define OVERLOAD_REP(_1, _2, _3, _4, name, ...) name
#define REP1(n) for(ll i=0;i<n;i++)
#define REP2(i, n) for (ll i=0;i<n;i++)
#define REP3(i, a, n) for (ll i=a;i<n;i++)
#define REP4(i, a, b, n) for(ll i=a;i<n;i+=b)
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_RREP(_1, _2, _3, _4, name, ...) name
#define RREP1(n) for(ll i=n;i>=0;i--)
#define RREP2(i, n) for(ll i=n;i>=0;i--)
#define RREP3(i, a, n) for(ll i=n;i>=a;i--)
#define RREP4(i, a, b, n) for(ll i=n;i>=a;i-=b)
#define rrep(...) OVERLOAD_RREP(__VA_ARGS__, RREP4, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define foa(a,v)  (auto& a : (v))
#define uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define len(n) (long long)(n).size()
#define pb push_back
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vs = vector<string>;
using vvs = vector<vs>;
using vvvs = vector<vvs>;
using vld = vector<ld>;
using vvld = vector<vld>;
using vvvld = vector<vvld>;
using vc = vector<char>;
using vvc = vector<vc>;
using vvvc = vector<vvc>;
using pll = pair<ll,ll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
template<class... T>
constexpr auto min(T... a){
    return min(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
constexpr auto max(T... a){
    return max(initializer_list<common_type_t<T...>>{a...});
}
template<class... T>
void input(T&... a){
    (cin >> ... >> a);
}
ll modpow(ll a,ll b,ll c){
    ll ans = 1;
    while (b){
        if (b & 1){
            ans *= a;
            ans %= c;
        }
        a *= a;
        a %= c;
        b /= 2;
    }
    return ans;
}
#define INT(...) int __VA_ARGS__; input(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; input(__VA_ARGS__)
#define CHA(...) char __VA_ARGS__; input(__VA_ARGS__)
#define VLL(name,length) vll name(length);rep(i,length){cin >> name[i];}
#define VVLL(name,h,w) vvll name(h,vll(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLL(name,a,b,c) vvvll name(a,vvll(b,vll(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VI(name,length) vi name(length);rep(i,length){cin >> name[i];}
#define VVI(name,h,w) vvi name(h,vi(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVI(name,a,b,c) vvvi name(a,vvll(b,vi(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VLD(name,length) vld name(length);rep(i,length){cin >> name[i];}
#define VVLD(name,h,w) vvld name(h,vld(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLD(name,a,b,c) vvvld name(a,vvld(b,vld(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VC(name,length) vc name(length);rep(i,length){cin >> name[i];}
#define VVC(name,h,w) vvc name(h,vc(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVC(name,a,b,c) vvvc name(a,vvc(b,vc(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VS(name,length) vs name(length);rep(i,length){cin >> name[i];}
#define VVS(name,h,w) vvs name(h,vs(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVS(name,a,b,c) vvvs name(a,vvs(b,vs(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define PLL(name) pll name;cin>>name.first>>name.second;
#define VPLL(name,length) vpll name(length);rep(i,length){cin>>name[i].first>>name[i].second;}

void print(){cout << "\n";}
template<class T, class... Ts>
void print(const T& a, const Ts&... b){cout << a;(cout << ... << (cout << ' ', b));cout << '\n';}
void print(vll x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void print(vvll x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void print(pll x){cout << x.first << ' ' << x.second << '\n';}
void solve(ll n,vll p){
    vll q;
    rep(i,n){
        q.push_back(p[i]);
        q[i] %= 1000;
    }
    vector<vector<pll>> dp(n+1,vpll(100000+10,{1LL<<60,1LL<<60}));
    dp[0][0] = {0,0};
    ll m = 100000+10;
    rep(i,n){
        rep(j,m){
            dp[i+1][j] = min(dp[i+1][j],dp[i][j]);
            if(1 <= q[i] && q[i] <= 500){
                dp[i+1][j + (1000 - q[i] - 500)] = min(dp[i+1][j + (1000 - q[i] - 500)],{dp[i][j].first - 1,dp[i][j].second + p[i]});
            }
            if(1 <= q[i] && j + 1000 - q[i] < m){
                dp[i+1][j + 1000 - q[i]] = min(dp[i+1][j + 1000 - q[i]],{dp[i][j].first,dp[i][j].second + p[i]});
            }
            if(0 <= j - (q[i] + 500) && q[i] + 500 < 1000){
                dp[i+1][j - (q[i] + 500)] = min(dp[i+1][j - (q[i] + 500)],{dp[i][j].first-1,dp[i][j].second + p[i]});
            }
            if(0 <= j - (q[i] + 500 - 1000) && q[i] + 500 >= 1000){
                dp[i+1][j - (q[i] + 500 - 1000)] = min(dp[i+1][j - (q[i] + 500 - 1000)],{dp[i][j].first - 1,dp[i][j].second + p[i]});
            }
        }
    }
    //print(dp[3][200]);
    pll ans = {0,1LL<<60};
    rep(i,m){
        ans = min(ans,dp[n][i]);
    }
    print(-ans.first,ans.second);
}

int main(){
    while(1){
        LL(n);
        if(n == 0){break;}
        VLL(p,n);
        solve(n,p);

    }
}
accuracy: 1
time_ms: 1850
memory_kb: 162816
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

template <unsigned mod = 1000000007> struct fp {
    unsigned v;
    static constexpr int get_mod() {
        return mod;
    }
    constexpr unsigned inv() const {
        assert(v != 0);
        int x = v, y = mod, p = 1, q = 0, t = 0, tmp = 0;
        while (y > 0) {
            t = x / y;
            x -= t * y, p -= t * q;
            tmp = x, x = y, y = tmp;
            tmp = p, p = q, q = tmp;
        }
        if (p < 0)
            p += mod;
        return p;
    }
    constexpr fp(ll x = 0) : v(x >= 0 ? x % mod : (mod - (-x) % mod) % mod) {}
    fp operator-() const {
        return fp() - *this;
    }
    fp pow(ull t) {
        fp res = 1, b = *this;
        while (t) {
            if (t & 1)
                res *= b;
            b *= b;
            t >>= 1;
        }
        return res;
    }
    fp &operator+=(const fp &x) {
        if ((v += x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator-=(const fp &x) {
        if ((v += mod - x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator*=(const fp &x) {
        v = ull(v) * x.v % mod;
        return *this;
    }
    fp &operator/=(const fp &x) {
        v = ull(v) * x.inv() % mod;
        return *this;
    }
    fp operator+(const fp &x) const {
        return fp(*this) += x;
    }
    fp operator-(const fp &x) const {
        return fp(*this) -= x;
    }
    fp operator*(const fp &x) const {
        return fp(*this) *= x;
    }
    fp operator/(const fp &x) const {
        return fp(*this) /= x;
    }
    bool operator==(const fp &x) const {
        return v == x.v;
    }
    bool operator!=(const fp &x) const {
        return v != x.v;
    }
    friend istream &operator>>(istream &is, fp &x) {
        return is >> x.v;
    }
    friend ostream &operator<<(ostream &os, const fp &x) {
        return os << x.v;
    }
};

template <unsigned mod> void rd(fp<mod> &x) {
    fastio::rd(x.v);
}
template <unsigned mod> void wt(fp<mod> x) {
    fastio::wt(x.v);
}

template <typename T> T Inv(ll n) {
    static const int md = T::get_mod();
    static vector<T> buf({0, 1});
    assert(n > 0);
    n %= md;
    while (SZ(buf) <= n) {
        int k = SZ(buf), q = (md + k - 1) / k;
        buf.push_back(buf[k * q - md] * q);
    }
    return buf[n];
}

template <typename T> T Fact(ll n, bool inv = 0) {
    static const int md = T::get_mod();
    static vector<T> buf({1, 1}), ibuf({1, 1});
    assert(n >= 0 and n < md);
    while (SZ(buf) <= n) {
        buf.push_back(buf.back() * SZ(buf));
        ibuf.push_back(ibuf.back() * Inv<T>(SZ(ibuf)));
    }
    return inv ? ibuf[n] : buf[n];
}

template <typename T> T nPr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nCr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(r, inv ^ 1) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nHr(int n, int r, bool inv = 0) {
    return nCr<T>(n + r - 1, r, inv);
}

/**
 * @brief Modint
 */

int MAXS = 50001;
static pair<int,int> DP[101][50001] = {};

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> C(N);
    rep(i,0,N) cin >> C[i];
    rep(i,0,101) {
        rep(j,0,50001) DP[i][j] = {-inf,-inf};
    }
    DP[0][0] = {0,0};
    rep(i,0,N) {
        rep(j,0,50001) {
            if (DP[i][j].first == -inf) continue;
            chmax(DP[i+1][j], DP[i][j]);
            if (1 <= (C[i] % 1000) && (C[i] % 1000) <= 500) {
                chmax(DP[i+1][j+((100000-C[i])%500)], {DP[i][j].first + 1, DP[i][j].second - C[i]});
            }
            else {
                int X;
                if (C[i] % 1000 == 0) X = 500;
                else X = C[i] % 500;
                if (j >= X) {
                    chmax(DP[i+1][j-X], {DP[i][j].first + 1, DP[i][j].second - C[i]});
                }
                chmax(DP[i+1][j+((100000-C[i])%500)], {DP[i][j].first, DP[i][j].second - C[i]});
            }
        }
    }
    pair<int,int> ANS = {-inf,-inf};
    rep(i,0,50001) chmax(ANS,DP[N][i]);
    cout << ANS.first << ' ' << -ANS.second << endl;
}
}
accuracy: 1
time_ms: 310
memory_kb: 42836
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for(int i = 0; i < n; i++)
#define MMAX 1000000000000000000LL

#define int ll

#define NO make_pair(-1, -1)

void main_()
{
    const int MAX = 1000 * 100;
    int n;
    cin >> n;
    if(!n) exit(0);

    vector<int> a(n);
    rep(i, n) cin >> a[i];
//    vector<vector<pair<int,int>>> dp(MAX, vector<pair<int,int>>(n + 1, NO));
    vector<pair<int,int>> dp(MAX, NO);

    dp[0] = make_pair(0, 0);

    for(int i = 0; i < n; i++) {
        vector<pair<int,int>> nxt = dp;
        for(int j = 0; j < MAX; j++) {
            if(dp.at(j).first == -1) continue;
            nxt.at(j) = max(nxt.at(j), dp.at(j));
            int change = j + (1000 - a[i] % 1000) % 1000;
            auto p = dp[j];
            nxt.at(change) = max(nxt.at(change), make_pair(p.first, p.second - a[i]));
            if(change < 500) continue;
            change -= 500;
            nxt.at(change) = max(nxt.at(change), make_pair(p.first + 1, p.second - a[i]));
        }
        dp = nxt;
    }

    pair<int,int> p = make_pair(0, 0);
    for(int i = 0; i < MAX; i++) {
        p = max(p, dp[i]);
    }
    cout << p.first << " " << -p.second << endl;
}

signed main()
{
    while(1) main_();
}
accuracy: 1
time_ms: 640
memory_kb: 6200
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef pair<int, int> pint;
const int MOD = 1000000007;
#define rep(i, N) for(int i = 0; i < (int)N; i++)
#define ALL(V)  (V).begin(), (V).end()
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

const int INF = 1e8;

template<class T> inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template<class T> inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

int dp[101][50001] = {INF};
int ndp[101][50001] = {INF};

int main() {
    while (1) {
        int N; cin >> N;
        if (N == 0) break;
        vector<int> P(N);
        rep (i, N) cin >> P[i];
        rep (i, 101) rep (j, 50001) dp[i][j] = INF, ndp[i][j] = INF;

        dp[0][0] = 0;
        int oturi = 0;
        rep (i, N) {
            if (i % 2 == 0) { // ndpを更新
                rep (k, N) {
                    rep (j, oturi + 1) ndp[k][j] = INF;
                }
                rep (k, N) {
                    rep (j, oturi + 1) {
                        // not buy
                        chmin(ndp[k][j], dp[k][j]);
                        int np = P[i] % 1000;
                        // buy
                        if (np == 0) {
                            // 小銭の500円があるならそれを一緒に払って500円玉を得る
                            if (j - 500 >= 0) chmin(ndp[k + 1][j - 500], dp[k][j] + P[i]);
                        } else if (np <= 500) {
                            // 1000円払って500円玉を得る
                            if (j + (1000 - np) % 500 <= 50000) chmin(ndp[k + 1][j + (1000 - np) % 500], dp[k][j] + P[i]);
                        } else if (np > 500) {
                            // 1000円払って小銭をもらう
                            if (j + (1000 - np) <= 50000) chmin(ndp[k][j + (1000 - np)], dp[k][j] + P[i]);
                            // 小銭を払って500円玉を得る
                            if (j - np % 500 >= 0) chmin(ndp[k + 1][j - np % 500], dp[k][j] + P[i]);
                        }
                    }
                }
            } else { // dpを更新
                rep (k, N) {
                    rep (j, oturi + 1) dp[k][j] = INF;
                }
                rep (k, N) {
                    rep (j, oturi + 1) {
                        // not buy
                        chmin(dp[k][j], ndp[k][j]);
                        int np = P[i] % 1000;
                        // buy
                        if (np == 0) {
                            // 小銭の500円があるならそれを一緒に払って500円玉を得る
                            if (j - 500 >= 0) chmin(dp[k + 1][j - 500], ndp[k][j] + P[i]);
                        } else if (np <= 500) {
                            // 1000円払って500円玉を得る
                            if (j + (1000 - np) % 500 <= 50000) chmin(dp[k + 1][j + (1000 - np) % 500], ndp[k][j] + P[i]);
                        } else if (np > 500) {
                            // 1000円払って小銭をもらう
                            if (j + (1000 - np) <= 50000) chmin(dp[k][j + (1000 - np)], ndp[k][j] + P[i]);
                            // 小銭を払って500円玉を得る
                            if (j - np % 500 >= 0) chmin(dp[k + 1][j - np % 500], ndp[k][j] + P[i]);
                        }
                    }
                }
            }
            oturi += (1000 - P[i] % 1000) % 500;
        }
        
        int ans_idx = 0;
        int ans_value = 0;
        if (N % 2 == 0) {
            rep (i, N + 1) {
                rep (j, 50001) {
                    if (dp[i][j] == INF) continue;
                    if (ans_idx < i) {
                        ans_idx = i;
                        ans_value = dp[i][j];
                        // cout << ans_idx << ' ' << ans_value << ' ' << j << endl;
                    } else if (ans_idx == i) {
                        chmin(ans_value, dp[i][j]);
                        // cout << ans_idx << ' ' << ans_value << ' ' << j << endl;
                    }
                }
            }
        } else {
            rep (i, N + 1) {
                rep (j, 50001) {
                    if (ndp[i][j] == INF) continue;
                    if (ans_idx < i) {
                        ans_idx = i;
                        ans_value = ndp[i][j];
                        // cout << ans_idx << ' ' << ans_value << ' ' << j << endl;
                    } else if (ans_idx == i) {
                        chmin(ans_value, ndp[i][j]);
                        // cout << ans_idx << ' ' << ans_value << ' ' << j << endl;
                    }
                }
            }
        }
        
        cout << ans_idx << ' ' << ans_value << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 4890
memory_kb: 42864
final_rank: 18

code_snippet: #include <bits/stdc++.h>

//使用したライブラリ
//https://github.com/atcoder/ac-library/tree/fe9b6fca9ab4e1be946ea23a4e6a2a751cf4aaa2
//https://github.com/ei1333/library/tree/7da7fca8cebc1d17a048c9483f07e39c8e465cdf
//https://github.com/zawa-tin/cp-documentation/tree/3842eb973aace809be0bcf1649e2fe85e99098e3
//https://github.com/luckylat/library/tree/8e2a2a6a58bef4644c9442998a1c9c1890672cd3

const int M{500 * 100 + 1};

int Ceil(int A, int B) {
    assert(B != 0);
    return (A + B - 1) / B;
}

std::pair<int, int> operator+(std::pair<int, int> A, std::pair<int, int> B) {
    return {A.first + B.first, A.second + B.second};
}

std::pair<int, int> chopt(std::pair<int, int> A, std::pair<int, int> B) {
    if (A.first < B.first) A = B;
    else if (A.first == B.first and A.second > B.second) A = B;
    return A;
}

bool solve() {
    int N;
    std::cin >> N;
    if (N == 0) return false;
    const std::pair<int, int> INVALID{ -1, -1 };
    std::vector<std::pair<int, int>> dp(M, INVALID);
    dp[0] = { 0, 0 };
    while (N--) {
        int P;
        std::cin >> P;
        std::vector<std::pair<int, int>> next{dp};
        for (int i{} ; i < M ; i++) {
            if (dp[i] == INVALID) continue;
            int turi{1000 * Ceil(P, 1000) - P};
            assert(0 <= turi and turi <= 1000);
            if (turi >= 500) {
                turi -= 500;
                next[i + turi] = chopt(next[i + turi], dp[i] + std::make_pair(1, P));
            }
            else {
                next[i + turi] = chopt(next[i + turi], dp[i] + std::make_pair(0, P));
                int need{500 - turi};
                if (need <= i) {
                    next[i - need] = chopt(next[i - need], dp[i] + std::make_pair(1, P));
                }
            }
        }
        dp = std::move(next);
    }
    int max{-1}, min{};
    for (int i{} ; i < M ; i++) {
        if (max < dp[i].first) {
            std::tie(max, min) = dp[i];
        }
        else if (max == dp[i].first and min > dp[i].second) {
            std::tie(max, min) = dp[i];
        }
    }
    std::cout << max << ' ' << min << '\n';
    return true;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    while (solve()) ;
}
accuracy: 1
time_ms: 210
memory_kb: 3896
final_rank: 2

code_snippet: #include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip>
#include <climits>
#include <cmath>
#include <functional>
#include <numeric>
#include <regex>
#include <array>
#include <fstream>
#include <sstream>

//#include<atcoder/modint>
//using namespace atcoder;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep1(i, n) for (int i = 1; i <= (int)(n); i++)
#define repl(i,l,r) for (int i = l; i < (int)(r); i++)
#define all(a) a.begin(),a.end()
#define Pii pair<int,int>
#define Pll pair<long,long>
#define INFi 1000000001
#define INFl 1000000000000000001
#define ll long long
using namespace std;



template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T> void printArray(vector<T>&A){
    for(T&a:A){
        cout<<a<<" ";
    }
    cout<<endl;
}
template<class T> void printArrayln(vector<T>&A){
    for(T&a:A){
        cout<<a<<endl;
    }
}


template<class T1,class T2> std::ostream &operator<<(std::ostream &out, const pair<T1,T2> &A){
    cout<<"{"<<A.first<<","<<A.second<<"}";
    return out;
}

template<class T1,class T2> std::ostream &operator<<(std::ostream &out, const map<T1,T2> &M){
    for(const auto&A:M){
        cout<<"{"<<A.first<<","<<A.second<<"}";
    }
    return out;
}

template<class T1> std::ostream &operator<<(std::ostream &out, const set<T1> &M){
    cout<<"{";
    for(const auto&A:M){
        cout<<A<<", ";
    }
    cout<<"}"<<endl;
    return out;
}


template<class T1> std::ostream &operator<<(std::ostream &out, const multiset<T1> &M){
    cout<<"{";
    for(const auto&A:M){
        cout<<A<<", ";
    }
    cout<<"}"<<endl;
    return out;
}

template<class T> std::ostream &operator<<(std::ostream &out, const vector<T> &A){
    for(const T &a:A){
        cout<<a<<" ";
    }
    return out;
}

void print() { cout << endl; }
 
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
  cout << H << " ";
  print(T...);
}


template<class T> std::istream &operator>>(std::istream &in,vector<T>&A){
    for(T&a:A){
        std::cin>>a;
    }
    return in;
}

struct dpn{
    int coins;
    int cost;
    // 比較関数
    bool operator<(const dpn &right) const {
        if(coins!=right.coins)return coins<right.coins;
        return cost>right.cost;
    }
};


void solve(int N){
    vector<int> P(N);
    rep(i,N)cin>>P[i];
    const int M = 499*100;
    vector<vector<dpn>> dp(N+1,vector<dpn>(M+1,{-10000,0}));
    dp[0][0] = {0,0};

    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            chmax(dp[i+1][j],dp[i][j]);
            // iを買う 1000円だけで
            int otsuri = (1000-P[i]%1000)%1000;
            bool coin = false;
            if(otsuri >= 500){
                coin = true;
                otsuri -= 500;
            }
            if(j+otsuri<=M){
                chmax(dp[i+1][j+otsuri],{dp[i][j].coins+coin,dp[i][j].cost+P[i]});
            }
            // 買う 小銭で
            int border = (P[i]+500)%1000;
            if(j>=border){
                chmax(dp[i+1][j-border],{dp[i][j].coins+1,dp[i][j].cost+P[i]});
            }
        }
    }
    // dpテーブルを表示
    for(int i=0;i<=N;i++){
        for(int j=0;j<=600;j++){
            if(dp[i][j].coins<0)continue;
            //cout << i << " " << j << " " << dp[i][j].coins << " " << dp[i][j].cost ;
            //cout << endl;

        }
    }

    auto ans = dp[N][0];
    for(int i=0;i<=M;i++){
        chmax(ans,dp[N][i]);
    }
    cout<<ans.coins<<" "<<ans.cost<<endl;


}

int main(void){
    std::cin.tie(0)->sync_with_stdio(0);
    while(1){
        int n;cin>>n;
        if(n==0)break;
        solve(n);
    }
}
accuracy: 1
time_ms: 930
memory_kb: 42936
final_rank: 15

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;

using ll = long long;
using i64 = long long;
using pll = pair<ll,ll>;
using plll = pair<pll,ll>;
using pii =pair<int,int>;

constexpr ll mod = 1000000007;

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int dX[4]={1,0,-1,0};
int dY[4]={0,-1,0,1};



//library

//end




using Graph =vector<vector<int>>;

int main(){
    while (true){
        int n;
        cin>>n;
        if (n==0)break;
        int m=50010;
        vector<vector<pii>> dp(n+1,vector<pii>(m,pair{-1,0}));
        dp[0][0].first=0;
        for (int i=0; i<n; i++){
            int p;
            cin>>p;
            for (int j=0; j<m; j++){
                if (dp[i][j].first==-1)continue;
                //cout<<' '<<i<<' '<<j<<' '<<dp[i][j].first<<endl;

                //p+500円払う
                if (j>=(p+500)%1000){
                    if (dp[i+1][j-(p+500)%1000].first<dp[i][j].first+1){
                        dp[i+1][j-(p+500)%1000].first=dp[i][j].first+1;
                        dp[i+1][j-(p+500)%1000].second=dp[i][j].second+p;

                    }
                    else if (dp[i+1][j-(p+500)%1000].second>dp[i][j].second+p && dp[i+1][j-(p+500)%1000].first==dp[i][j].first+1){
                        dp[i+1][j-(p+500)%1000].first=dp[i][j].first+1;
                        dp[i+1][j-(p+500)%1000].second=dp[i][j].second+p;
                    }
                }

                //1000円札だけで払う
                int s=(p+999)/1000;
                if (1000*s-p>=500){
                    if (dp[i+1][j+1000*s-p-500].first<dp[i][j].first+1){
                        dp[i+1][j+1000*s-p-500].first=dp[i][j].first+1;
                        dp[i+1][j+1000*s-p-500].second=dp[i][j].second+p;

                    }
                    else if (dp[i+1][j+1000*s-p-500].second>dp[i][j].second+p && dp[i+1][j+1000*s-p-500].first==dp[i][j].first+1){
                        dp[i+1][j+1000*s-p-500].first=dp[i][j].first+1;
                        dp[i+1][j+1000*s-p-500].second=dp[i][j].second+p;
                    }
                }
                else{
                    if (dp[i+1][j+1000*s-p].first<dp[i][j].first){
                        //cout<<'!'<<endl;
                        dp[i+1][j+1000*s-p].first=dp[i][j].first;
                        dp[i+1][j+1000*s-p].second=dp[i][j].second+p;
                        //cout<<dp[i+1][j+1000*s-p].first<<' '<<dp[i+1][j+1000*s-p].second<<endl;

                    }
                    else if (dp[i+1][j+1000*s-p].second>dp[i][j].second+p && dp[i+1][j+1000*s-p].first==dp[i][j].first){

                        dp[i+1][j+1000*s-p].first=dp[i][j].first;
                        dp[i+1][j+1000*s-p].second=dp[i][j].second+p;
                    }
                }

                //i番目の品物を買わない
                if (dp[i+1][j].first<dp[i][j].first){
                    dp[i+1][j].first=dp[i][j].first;
                    dp[i+1][j].second=dp[i][j].second;

                }
                else if (dp[i+1][j].first==dp[i][j].first && dp[i][j].second<dp[i+1][j].second){
                    dp[i+1][j].first=dp[i][j].first;
                    dp[i+1][j].second=dp[i][j].second;
                }

            }

        }
        int a1=0,a2=0;
        for (int j=0; j<m; j++){
            auto[a,b]=dp[n][j];
            //cout<<a<<b<<endl;
            if (a>a1){
                a1=a;
                a2=b;
            }
            if (a==a1 && a2>b){
                a1=a;
                a2=b;
            }
        }

        cout<<a1<<' '<<a2<<endl;


    }




}
accuracy: 1
time_ms: 480
memory_kb: 43080
final_rank: 12

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using P = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
#define rep(i,n) for(ll i = 0;i < (ll)n;i++)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  while(1){
    int n;cin >> n;
    if(!n)break;
    vi p(n);cin >> p;
    int MX = 1000*n+10;
    vector<P> dp(MX,{-1,1ll << 50});
    dp[0] = {0,0};
    auto f = [](P &a,P b)->void{
      if(a.first > b.first)return;
      if(a.first == b.first && a.second <= b.second)return;
      swap(a,b);
    };
    rep(i,n){
      vector<P> DP(MX,{-1,1ll << 50});
      rep(j,MX){
        if(dp[j].first == -1)continue;
        int g = p[i]%1000;
        if(0 < g && g <= 500){
          f(DP[j+500-g],{dp[j].first+1,dp[j].second+p[i]});
          f(DP[j],dp[j]);
        }else{
          int k = g%500;
          if(k == 0)k += 500;
          if(k <= j)f(DP[j-k],{dp[j].first+1,dp[j].second+p[i]});
          f(DP[j],dp[j]);
          if(g != 0)f(DP[j+1000-g],{dp[j].first,dp[j].second+p[i]});
        }
      }
      swap(dp,DP);
    }
    P res = {-1,1ll << 50};
    rep(i,MX)f(res,dp[i]);
    cout << res << "\n";
  }
  

  return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 6220
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;

const long long inf = 1000000000000000000LL;

int main() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;

        vector<int> P(n);
        for (int i = 0; i < n; ++i) {
            cin >> P[i];
        }

        int k_max = 5 * n + 1;
        int j_max = n + 1;
        vector<vector<vector<long long>>> dp(n + 1, vector<vector<long long>>(j_max, vector<long long>(k_max, -inf)));
        
        // dp[i個目の店][j枚500円玉もらう][k枚1000円札払う] = 小銭合計
        dp[0][0][0] = 0;
        
        for (int i = 0; i < n; ++i) {
            int d = P[i] / 1000;
            int m = P[i] % 1000;
            for (int j = 0; j < j_max; ++j) {
                for (int k = 0; k < k_max; ++k) {
                    if (dp[i][j][k] == -inf) continue;

                    if (m == 0) {
                        dp[i+1][j][k] = max(dp[i+1][j][k], dp[i][j][k]);
                        if (dp[i][j][k] >= 500 && j + 1 < j_max && k + d < k_max) {
                            dp[i+1][j+1][k+d] = max(dp[i+1][j+1][k+d], dp[i][j][k] - 500);
                        }
                    } else if (m <= 500) {
                        if (j + 1 < j_max && k + d + 1 < k_max) {
                            dp[i+1][j+1][k+d+1] = max(dp[i+1][j+1][k+d+1], dp[i][j][k] + 500 - m);
                        }
                    } else {
                        dp[i+1][j][k] = max(dp[i+1][j][k], dp[i][j][k]);
                        if (k + d + 1 < k_max) {
                            dp[i+1][j][k+d+1] = max(dp[i+1][j][k+d+1], dp[i][j][k] + 1000 - m);
                        }
                        if (dp[i][j][k] >= m - 500 && j + 1 < j_max && k + d + 1 < k_max) {
                            dp[i+1][j+1][k+d+1] = max(dp[i+1][j+1][k+d+1], dp[i][j][k] - (m - 500));
                        }
                    }
                }
            }
        }

        int c = 0;
        for (int i = 0; i < j_max; ++i) {
            for (int k = 0; k < k_max; ++k) {
                if (dp[n][i][k] >= 0) {
                    c = max(c, i);
                }
            }
        }

        int mn = INT_MAX;
        for (int i = 0; i < k_max; ++i) {
            if (dp[n][c][i] >= 0) {
                mn = min(mn, i);
            }
        }

        long long s = 1000LL * mn - dp[n][c][mn] - c * 500LL;
        cout << c << " " << s << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 43708
final_rank: 11

code_snippet: #include<iostream>
#include<algorithm>
using namespace std;
void chmin(int &a, int b){if(a>b)a=b;}
int N,P,Q;
const int INF=1<<25;
const int M=4000;
int dp[101][M+500],ep[101][M+500];
bool solve()
{
    cin>>N;
    if(N==0)return 0;
    for(int i=0;i<=N;i++)for(int j=0;j<M;j++)dp[i][j]=INF;
    dp[0][0]=0;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<=N;j++)for(int k=0;k<M;k++)ep[j][k]=INF;
        cin>>P;
        Q=P%1000;
        for(int j=0;j<=N;j++)for(int k=0;k<M;k++)
        {
            chmin(ep[j][k],dp[j][k]);
            if(Q==0)
            {
                if(k>=500)chmin(ep[j+1][k-500],dp[j][k]+P);
            }
            else if(Q==500)
            {
                chmin(ep[j+1][k],dp[j][k]+P);
            }
            else if(Q<500)
            {
                chmin(ep[j+1][k+500-Q],dp[j][k]+P);
                if(k-500>=Q)chmin(ep[j+1][k-500-Q],dp[j][k]+P);
            }
            else
            {
                chmin(ep[j][k+1000-Q],dp[j][k]+P);
                if(k+500>=Q)chmin(ep[j+1][k+500-Q],dp[j][k]+P);
                if(k-500>=Q)chmin(ep[j+1][k-500-Q],dp[j][k]+P);
            }
        }
        swap(dp,ep);
    }
    for(int j=N;j>=0;j--)
    {
        int ans=*min_element(dp[j],dp[j]+M);
        if(ans<INF)
        {
            cout<<j<<' '<<ans<<'\n';
            return 1;
        }
    }
    return 1;
}
int main(){while(solve()){}}
accuracy: 0.5
time_ms: 3080
memory_kb: 6984
final_rank: 20