結果

問題 No.10 +か×か
ユーザー yuma25689yuma25689
提出日時 2015-11-07 11:58:37
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 20 ms / 5,000 ms
コード長 3,708 bytes
コンパイル時間 649 ms
コンパイル使用メモリ 65,332 KB
実行使用メモリ 5,248 KB
最終ジャッジ日時 2024-12-14 15:33:02
合計ジャッジ時間 1,385 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 1 ms
5,248 KB
testcase_03 AC 18 ms
5,248 KB
testcase_04 AC 8 ms
5,248 KB
testcase_05 AC 2 ms
5,248 KB
testcase_06 AC 20 ms
5,248 KB
testcase_07 AC 9 ms
5,248 KB
testcase_08 AC 4 ms
5,248 KB
testcase_09 AC 7 ms
5,248 KB
testcase_10 AC 1 ms
5,248 KB
testcase_11 AC 2 ms
5,248 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <vector>
#include <iostream>

// N
// Total
// A1 A2 … AN
// 1行目に、計算式中の整数の数を表すN (2≤N≤50)が与えられる。
// 2行目に、計算式の演算結果を表すTotal (1≤Total≤100,000)が与えられる。
// 3行目に 計算式中の整数を表すAi (1≤Ai≤10) がスペース区切りでN個与えられる。

// +と*しかなくて(つまり、増加のみ)、Totalが最大100000なので、演算結果自体も100000超えはありえないとみなして良いのではないだろうか・・・。

using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
typedef vector<int>::iterator ITR;
typedef unsigned long long ULONGLONG;

static const ULONGLONG INF=1ULL<<63;

int main(void) {
    
    int nIntCount = 0;
    long nTotal = 0;
    vector<int> vInt;
    
    cin >> nIntCount;
    cin >> nTotal;
    int nInput = 0;
    REP(i,nIntCount)
    {
        cin >> nInput;
        vInt.push_back(nInput);
    }
    //    cout << nIntCount << endl;
    //    cout << nTotal << endl;
    //    REP(nIntCount) cout << vInt[i] << endl;
    // 計算結果の配列
    // この値は、64bit整数だが、イメージ的には、各1bitがフラグとなって加算か乗算かを表現しているイメージ?
    // ただし、乗算は+1して1桁上まで行かせる
    vector<ULONGLONG> vRes(nTotal+1, INF);
    vRes[vInt[0]] = 0;
    
    for(int i=1;i<nIntCount;i++)
    {
        // 項の数ループ
        // 各項毎に、一時的なメモ配列を作成
        // (例)
        // total 6
        // 2 3 1
        // であれば
        // vRes[2]==0
        // vRetTmp[2+3]=VResTmp[2+3] or vRes[2] << 1
        // vRetTmp[2*3]=VResTmp[2*3] or vRes[2] << 1
        // => vResに保存&今回計算されていない余計なのは消える
        // (※要は、2回目のループで、下記情報はあってはいけない)
        // vRes[2]==0
        //
        // 多分、2回目のループでは、vRes[5],vRes[6]のみになっていなければならない
        vector<ULONGLONG> vResTmp(nTotal+1, INF);
        REP(j,nTotal+1)
        {
            // 各項毎に、可能性のある数値を更新
            // この条件より、前に通った値として保存されているもの以外、計算しないことになる?
            if( vRes[j] == INF ) continue;
            
            // jが途中で通る値の1つである
            // それに現在値を加算または乗算したところに値としてこれまでの演算子パターンを設定
            if( j + vInt[i] <= nTotal )
                // 値が小さい方が+ 大きい方が*と思われる この問題の場合は+優先
                // 該当のビットを立てる(だんだん桁が上がるはず)
                vResTmp[j + vInt[i]] = min( vResTmp[j + vInt[i]], vRes[j] << 1 );
            if( j * vInt[i] <= nTotal )
                // 該当のビットを立ててから+1(だんだん桁が上がるはず)
                // *の場合 +1は、後で+か*かを見分けるのに使用
                vResTmp[j * vInt[i]] = min( vResTmp[j * vInt[i]], (vRes[j] << 1) + 1 );//| (1<<j) );
        }
        // 一時領域で正規の領域を上書き
        // これで、前の情報は一部消えると思われる
        vRes = vResTmp;
    }
    ULONGLONG llAns = vRes[nTotal];
    REP(i,nIntCount-1)
    {
        ULONGLONG tmp = llAns>>(nIntCount-i-2);
        //if( (tmp & 0x1 ) == 1 )
        if( tmp % 2 == 1 )
        {
            cout << '*';
        }
        else
        {
            cout << '+';
        }
    }
    cout << endl;
    
    return 0;
}
0