結果

問題 No.5021 Addition Pyramid
ユーザー Isshii
提出日時 2025-02-25 22:59:27
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 1,784 ms / 2,000 ms
コード長 5,572 bytes
コンパイル時間 4,969 ms
コンパイル使用メモリ 308,440 KB
実行使用メモリ 6,820 KB
スコア 10,679,036
最終ジャッジ日時 2025-02-25 23:02:01
合計ジャッジ時間 97,758 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます

ソースコード

diff #

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

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

using namespace std;
//using namespace atcoder;

typedef long long ll;
typedef unsigned long long ull;

#define rep(i,N) for(int i=0;i<(N);++i)
#define rrep(i,N) for(int i=(N)-1;i>=0;--i)
#define all(A) A.begin(),A.end()

using vvi = vector<vector<int>>;
using P = pair<int,int>;

template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T=bool> void YesNo(T flg){ cout << (flg? "Yes\n" : "No\n"); }

//時間管理
const double TimeLimit=1780;
std::chrono::system_clock::time_point start;
std::chrono::system_clock::time_point finish;
inline void TimerStart(){
    start=finish=chrono::system_clock::now();
}
inline void TimerUpdate(){
    finish=chrono::system_clock::now();
}
double TimeDist(){
    return chrono::duration_cast<chrono::milliseconds>(finish-start).count();
}

random_device rnd;
mt19937 mt(rnd());
default_random_engine eng(rnd());
int NextInt(int minval,int maxval) {
    uniform_int_distribution<int> distr(minval,maxval);
    return distr(mt);
}

vector<vector<vector<ll>>> cross;
const ll Mod=1e8;

namespace Input{
    int N;
    vector<vector<ll>> A;
    void Init(){
        cin >> N;
        A.resize(N);
        rep(i,N){
            rep(j,i+1){
                ll a;cin >> a;
                A[i].push_back(a);
            }
        }
        cross.resize(N,vector<vector<ll>>(N,vector<ll>(N,0)));
        rep(i,N){
            cross[i][N-1][i]=1;
            rrep(j,N){
                rep(k,j+1){
                    cross[i][j][k]%=Mod;
                    if(k<j) cross[i][j-1][k]+=cross[i][j][k];
                    if(k) cross[i][j-1][k-1]+=cross[i][j][k];
                }
            }
        }
    }
};

struct Pyramid{
    int N;
    vector<vector<ll>> pyramid;
    vector<vector<ll>> dist;
    vector<vector<ll>> score;

    ll maxScore;
    P maxPos;

    void Init(){
        N=Input::N;
        maxScore=0;
        pyramid.resize(N,vector<ll>(N,0));
        dist.resize(N,vector<ll>(N,0));
        score.resize(N,vector<ll>(N,0));
        rep(i,N){
            pyramid[N-1][i]=Input::A[N-1][i];
        }
        for(int i=N-1;i>0;--i){
            rep(j,i+1){
                if(j<i) pyramid[i-1][j]+=pyramid[i][j];
                if(j) pyramid[i-1][j-1]+=pyramid[i][j];
            }
        }
        rep(i,N){
            rep(j,i+1){
                ScoreUpdate(i,j);
                if(chmax(maxScore,score[i][j])){
                    maxPos={i,j};
                }
            }
        }
    }

    /// @brief 最下段(N-1,y)の数値をvalue分だけ変更する
    /// @param y 最下段の何個目か
    /// @param value 変化量
    void Update(const int& y,const ll& value){
        maxScore=0;
        rep(i,N){
            rep(j,i+1){
                ll add=value*cross[y][i][j];
                add%=Mod;
                pyramid[i][j]+=add;
                if(cross[y][i][j]){
                    if(pyramid[i][j]<0){
                        pyramid[i][j]=Mod-abs(pyramid[i][j]%Mod);
                    }
                    pyramid[i][j]%=Mod;
                    ScoreUpdate(i,j);
                }
                if(chmax(maxScore,score[i][j])){
                    maxPos={i,j};
                }
            }
        }
    }

    // ll UpdateDown(const P& pos,const ll& val){
    //     if(val==0) return 0;

    //     ll subValue=0;
    //     if(x>N-1){
    //         if(pyramid[x+1][y]<=0 && pyramid[x+1][y+1]<=0){
    //             ll 
    //         }
    //     }
    //     auto [x,y]=pos;
    //     pyramid[x][y]+=val;
    //     if(pyramid[i][j]<0){
    //         pyramid[i][j]=Mod-abs(pyramid[i][j]%Mod);
    //     }
    //     pyramid[i][j]%=Mod;
    //     ScoreUpdate(x,y);
    //     return subValue;
    // }

    void ScoreUpdate(const int& x,const int& y){
        score[x][y]=GetScore(x,y);
    }

    ll GetScore(const int& x,const int& y){
        ll d=Input::A[x][y]-pyramid[x][y];
        dist[x][y]=d;
        d=abs(d);
        return min(d,Mod-d);
    }
};

struct Solver{
    int N;
    Pyramid pyramid;

    ll bestScore;
    vector<ll> bestAns;

    void Init(){
        N=Input::N;
        pyramid.Init();
        bestScore=pyramid.maxScore;
        bestAns=pyramid.pyramid[N-1];
    }

    void Solve(){
        TimerStart();
        while(TimeDist()<TimeLimit){
            auto[x,y]=pyramid.maxPos;
            int l=pyramid.maxPos.second;
            int r=pyramid.maxPos.second+(N-pyramid.maxPos.first-1);
            int target=NextInt(l,r);
            ll targetDist=1250000*(2.0-TimeDist()/TimeLimit);
            ll targetValue=NextInt(max(0ll,Input::A[x][y]-targetDist),min(Mod-1ll,Input::A[x][y]+targetDist));
            ll value=targetValue-pyramid.pyramid[x][y];
            pyramid.Update(target,value);
            if(chmin(bestScore,pyramid.maxScore)){
                bestAns=pyramid.pyramid[N-1];
            }
            TimerUpdate();
        }
    }

    void Output(){
        rep(i,N){
            if(i) cout << " ";
            cout << bestAns[i];
        }
        cout << endl;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    Input::Init();

    Solver solver;
    solver.Init();
    solver.Solve();
    solver.Output();

    return 0;
}
0