結果

問題 No.2792 Security Cameras on Young Diagram
ユーザー kaliafluoridokaliafluorido
提出日時 2024-06-21 22:19:34
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 7,434 bytes
コンパイル時間 6,994 ms
コンパイル使用メモリ 337,088 KB
実行使用メモリ 222,772 KB
最終ジャッジ日時 2024-06-21 22:19:47
合計ジャッジ時間 12,190 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
13,764 KB
testcase_01 AC 2 ms
6,812 KB
testcase_02 AC 2 ms
6,816 KB
testcase_03 AC 86 ms
15,512 KB
testcase_04 AC 218 ms
29,000 KB
testcase_05 AC 46 ms
10,008 KB
testcase_06 AC 174 ms
28,064 KB
testcase_07 AC 106 ms
18,456 KB
testcase_08 AC 104 ms
18,588 KB
testcase_09 AC 42 ms
9,372 KB
testcase_10 AC 93 ms
16,792 KB
testcase_11 AC 186 ms
28,204 KB
testcase_12 TLE -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifdef LOCAL_ENV
#include <header_all.hpp>
#else
#include <bits/stdc++.h>
#include <atcoder/all>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
#endif

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

using namespace std;
using namespace atcoder;
using namespace __gnu_pbds;

#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define FOR(i, start, end) for (int i = start; i < (int)(end); ++i)
#define RFOR(i, rstart, rend) for (int i = rstart; i >= (int)(rend); --i)
#define REP(i, end) FOR(i, 0, end)
#define BIT(x, i) (((x)>>(i))&1)
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pli = pair<ll, int>;
template<typename T> void read(T& val) {cin >> val;}
template<typename T, typename... Args> void read(T& val, Args&... args) {cin >> val;read(args...);}
#define DEF(type, ...) type __VA_ARGS__;read(__VA_ARGS__)
constexpr ll LINF = 1LL << 60;
constexpr int INF = 1 << 30;
template <typename T> using TREE = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T> using Graph = vector<vector<T>>;
template <typename T> using PQ = priority_queue<T, vector<T>, greater<T>>;
void yes(bool expr) {cout << (expr ? "Yes" : "No") << "\n";}
template<typename T> bool chmax(T &a, const T &b) { if (a<b){a=b; return true;} else{return false;}}
template<typename T> bool chmin(T &a, const T &b) { if (b<a){a=b; return true;} else{return false;}}
template<typename T> istream &operator>>(istream&is,vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> ostream &operator<<(ostream&os,const vector<T>&v){for(auto it=v.begin();it!=v.end();){os<<*it<<((++it)!=v.end()?" ":"\n");}return os;}

template<class T>
struct Binomial{
	std::vector<T> fact_vec, fact_inv_vec;
	void extend(int m = -1){
        int n = fact_vec.size();
        if (m == -1) m = n * 2;
        if (n >= m) return;
        fact_vec.resize(m);
        fact_inv_vec.resize(m);
        for (int i = n; i < m; i++){
            fact_vec[i] = fact_vec[i - 1] * T(i);
        }
        fact_inv_vec[m - 1] = T(1) / fact_vec[m - 1];
        for (int i = m - 1; i > n; i--){
            fact_inv_vec[i - 1] = fact_inv_vec[i] * T(i);
        }
    }
    Binomial(int MAX = 2){
        fact_vec.resize(1, T(1));
        fact_inv_vec.resize(1, T(1));
        extend(MAX + 1);
    }

    T fact(int i){
        if (i < 0) return 0;
        while (int(fact_vec.size()) <= i) extend();
        return fact_vec[i];
    }
    T invfact(int i){
        if (i < 0) return 0;
        while (int(fact_inv_vec.size()) <= i) extend();
        return fact_inv_vec[i];
    }
    T C(int a, int b){
        if (a < b || b < 0) return 0;
        return fact(a) * invfact(b) * invfact(a - b);
    }
    T invC(int a, int b){
        if (a < b || b < 0) return 0;
        return fact(b) * fact(a - b) *invfact(a);
    }
    T P(int a, int b){
        if (a < b || b < 0) return 0;
        return fact(a) * invfact(a - b);
    }
    T inv(int a){
        if (a < 0) return inv(-a) * T(-1);
        if (a == 0) return 1;
        return fact(a - 1) * invfact(a);
    }
};
/* 文字列、数列が一様か判定 */
template <typename T> struct UniformSegmentChecker {
	const T &v; const int n; vector<int> diff;
	UniformSegmentChecker(const T &v) : v(v), n(v.size()), diff(v.size(),0) { REP(i,n-1){ diff[i+1] = diff[i] + (v[i] != v[i+1]);} }
	bool is_uniform(int l, int r) const { assert(0 <= l && l < r && r <= n); return diff[l] == diff[r-1]; }
};
/* 回文判定 */ bool isPalindrome(const string &s){int sz=s.size(); REP(i,sz/2){if(s[i]!=s[sz-1-i])return false;} return true;}
/* 座標圧縮 */ template<typename T> vector<int> compress(const vector<T>&A){vector<int> ret(A.size()); auto tmp = A; sort(ALL(tmp)); tmp.erase(unique(ALL(tmp)), tmp.end()); REP(i,A.size()) ret[i] = lower_bound(ALL(tmp), A[i]) - tmp.begin(); return ret;}
/* 約数列挙 整数nの約数のvectorを返す */ vector<ll> enumdiv(ll n){vector<ll>s; for(ll i = 1;i*i<=n;i++){if(n%i==0){s.push_back(i);if(i*i!=n)s.push_back(n/i);}}return s;}
/* 素因数分解 pair<素数、指数>のvectorを返す */ vector<pli> primeDecomposition(ll x){vector<pli> ret;int i=2,sq=99,d=2;while(i<=sq){int k=0;while(x%i==0){x/=i;++k;}if(k>0){ret.emplace_back(i,k);}if(k>0 || i==97) {sq = sqrt(x)+0.5;}if(i<4){i = (i<<1)-1;}else{i += d;d ^= 6;}}if(x>1) ret.emplace_back(x,1);return ret;}
/* エラトステネスの篩 n未満の素数を列挙。isprimeには素数かどうかが入っている */ vector<bool> isprime;vector<int> era(int n) {isprime.resize(n, true);vector<int> res;isprime[0] = false; isprime[1] = false;for (int i = 2; i < n; ++i){if (isprime[i]) {res.push_back(i);for (int j = i*2; j < n; j += i) isprime[j] = false;}}return res;}
/* トポロジカルソート */ vector<int> topo_sort(const Graph<int> &G){int n = G.size();vector<int> deg(n), ret;for(const auto &v:G)for(const auto &to:v) ++deg[to];queue<int> que;REP(i,n) if(deg[i]==0)que.push(i);while(!que.empty()){const int from = que.front();que.pop();ret.push_back(from);for(const auto &to:G[from])if(--deg[to]==0) que.push(to);}return ret;};
/* 拡張ユークリッドの互除法 [gcd,x,y] ax+by=gcd(a,b) */ tuple<ll,ll,ll> ex_gcd(ll a, ll b){if(b==0) return {a,1,0}; auto [g,x,y] = ex_gcd(b, a%b); return {g,y,x-a/b*y};}
/* 辞書順で次の分割数を求める */ template<typename T> bool next_partition(vector<T> &a){const int n = a.size(); if(n<=1) {return false;} T sum=a[n-1]; a.pop_back(); while(true){T x = a.back(); a.pop_back(); sum += x; if(a.empty() || a.back() > x){a.push_back(x+1); a.resize(a.size()+sum-x-1, 1); break;}} return true;}
/* iを中心として回文となる半径を全て求める O(n) */ template <typename T> vector<int> manachar(const T &s) {int n = s.size();vector<int>r(n);int i=0,j=0;while(i<n){while(i-j>=0&&i+j<n&&s[i-j]==s[i+j]){++j;}r[i]=j;int k=1;while(k<j&&k+r[i-k]<j) {r[i+k]=r[i-k],++k;}i+=k;j-=k;}return r;}

using mint = modint998244353;
//using mint = modint1000000007;
//using mint = modint;
istream &operator>>(istream&is,mint&p){ll x;cin >> x;p=x; return is;}
ostream &operator<<(ostream&os,const mint&p){os << p.val();return os;}

struct HashPair {

    static size_t m_hash_pair_random;

    template<class T1, class T2>
    size_t operator()(const pair<T1, T2> &p) const {

        auto hash1 = hash<T1>{}(p.first);
        auto hash2 = hash<T2>{}(p.second);

        size_t seed = 0;
        seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

size_t HashPair::m_hash_pair_random = (size_t) random_device()();

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

	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++) cin >> a[i];
	unordered_map<pair<int, int>, mint, HashPair> memo;
	auto dfs = [&](auto &&f, int x, int y) -> mint {
		if(memo.count({x,y})) return memo[{x,y}];
		mint res = 0;
		if(x==n-1){
			res += 1;
		}else if(a[x+1] <= y) res += 1;
		else res += f(f, x+1, y);
		if(y == a[x]-1) res += 1;
		else res += f(f, x, y+1);
		memo[{x,y}] = res;
		return res;
	};
	cout << dfs(dfs, 0, 0) << endl;

	return 0;
}
0