其他分享
首页 > 其他分享> > [题解]不会真有人要打树套树吧

[题解]不会真有人要打树套树吧

作者:互联网

\[\color{red}{\text{校长者,真神人也,左马桶,右永神,会执利笔破邪炁,何人当之?}} \\ \begin{array}{|} \hline \color{pink}{\text{The principal is really a god}} \\ \color{pink}{\text{with a closestool on the left and Yongshen on the right}} \\ \color{pink}{\text{holding a sharp pen to pierce the truth}} \\ \color{pink}{\text{Who can resist him? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{green}{\text{校長は本当に神であり、左側にトイレ、右側にヨンシェンがあり}} \\ \color{green}{\text{鋭いペンを持って真実を突き刺している。誰が彼に抵抗できるだろうか? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{lightblue}{\text{Le principal est vraiment un dieu}} \\ \color{lightblue}{\text{avec des toilettes à gauche et Yongshen à droite}} \\ \color{lightblue}{\text{tenant un stylo pointu pour percer la vérité}} \\ \color{lightblue}{\text{Qui peut lui résister ? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{purple}{\text{Der Direktor ist wirklich ein Gott}} \\ \color{purple}{\text{mit einer Toilette links und Yongshen rechts}} \\ \color{purple}{\text{der einen spitzen Stift hält}} \\ \color{purple}{\text{um die Wahrheit zu durchdringen.}} \\ \color{purple}{\text{Wer kann ihm widerstehen? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{cyan}{\text{Principalis deus est, Yongshen a dextris cum latrina}} \\ \color{cyan}{\text{acuto stylo ad perforandum veritatem: quis resistet ei? }} \\ \hline \end{array} \\ \color{red}{\text{对曰:“无人,狗欲当之,还请赐教!”}} \\ \newcommand\brak[1]{\left({#1}\right)} \newcommand\Brak[1]{\left\{{#1}\right\}} \newcommand\d[0]{\text{d}} \newcommand\string[2]{\genfrac{\{}{\}}{0pt}{}{#1}{#2}} \newcommand\down[2]{{#1}^{\underline{#2}}} \newcommand\ddiv[2]{\left\lfloor\frac{#1}{#2}\right\rfloor} \newcommand\udiv[2]{\left\lceil\frac{#1}{#2}\right\rceil} \newcommand\lcm[0]{\operatorname{lcm}} \newcommand\set[1]{\left\{{#1}\right\}} \newcommand\ceil[1]{\left\lceil{#1}\right\rceil} \newcommand\floor[1]{\left\lfloor{#1}\right\rfloor} \newcommand\rhs[1]{\;\text{Rhs}\;#1} \newcommand\lhs[1]{\;\text{Lhs}\;#1} \newcommand\Vec[1]{\vec{\mathbf{#1}}} \newcommand\rank[0]{\text{rank}} \]

  \(\mathcal{Back\;To\;The\;Menu}\).

2022-03-19 不会真有人要打树套树吧

  T2 花的时间太多了,还是不大行。

太阳照常升起 / Lost

  注意到 \(\tau(n)\) 是个完全积性函数,而 \(\xi=\tau*1\),那 \(\xi(n)\) 也就是积性函数。由于 \(\xi(p)(p\in \Bbb P)\),因此,你会发现 \(\xi(n)\) 有值当且仅当 \(n\) 为完全平方数,且此时 \(\xi(n)=1\).

  因此现在的问题就变成了求可重集 \(\set{ij|1\le i\le n,1\le j\le m}\) 中有多少是完全平方数,由经典结论:若 \(ab\) 为完全平方数,那么存在 \(m,s,t\) 使得 \(ms^2=a,mt^b=b\) 且 \(\mu(m)\neq 0\)(即 \(m\) 中不含平方因子),因此,我们可以考虑枚举这个 \(m\):

\[\sum_{i=1}^n\floor{\sqrt{\ddiv{n}{i}}}\floor{\sqrt{\ddiv{m}{i}}}\mu^2(i) \]

  其中含有 \(\mu^2(i)\) 是指我们只统计 \(\mu(i)\neq 0\) 的 \(i\). 走到这一步之后,你可以使用 \(\mathcal O(\sqrt n)\) 的复杂度来解决这个问题,只是你需要求得 \(\sum \mu^2(i)\),这个东西挺困难,因此我们需要将其再一步变形,,考虑使用一个替换:\(\displaystyle \mu^2(i)=\sum_{d^2\mid i}\mu(d)\),其证明可以使用贝尔级数:

  不难知道 \(\mu^2_p(z)=1+z,\mu_p(z)=1-z,1_p(z)=\frac{1}{1-z}\),因此 \(\mu^2_p(z)=\mu_p(z^2)\times 1_p(z)\),其中 \(\mu_p(z^2)\) 即要求 \(d^2\mid i\),然后就是 \(\mu\) 卷上 \(1\).

  然后继续推式子:

\[(*)=\sum_{i=1}^n\floor{\sqrt{\ddiv{n}{i}}}\floor{\sqrt{\ddiv{m}{i}}}\sum_{d^2\mid i}\mu(d)=\sum_{d=1}^{\sqrt n}\mu(d)\sum_{i=1}^n\floor{\sqrt{\ddiv{n}{id^2}}}\floor{\sqrt{\ddiv{m}{id^2}}} \]

  注意后面的根号部分可以数论分块,此时总复杂度就是 \(\mathcal O(\sqrt n\ln n)\). 但是宋队积出来发现时间复杂度只是 \(\mathcal \require{enclose}\enclose{horizontalstrike}{O(\sqrt n)}\) 的,并不明白对数是哪里来的。

/** @author __Elaina__ */

// #pragma GCC optimize("O2")

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

#define USING_FREAD
// #define NDEBUG
#include <cassert>

namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */

#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)

typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;

template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }

#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
    static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
    return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI ((char)getchar())
#endif

template<class T> inline T readret(T x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    return f ? -x : x;
}
template<class T> inline void readin(T& x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
    readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
    if (x < 0) putchar('-'), x = -x;
    static int __stk[55], __bit = 0;
    do __stk[++__bit] = x % 10, x /= 10; while (x);
    while (__bit) putchar(__stk[__bit--] ^ 48);
    putchar(c);
}
template<class T> inline T listMax(const T& x) { return x; }
template<class T, class... Args> inline T listMax(const T& x, const Args&... args) {
    return max(x, listMax(args...));
}
template<class T> inline T listMin(const T& x) { return x; }
template<class T, class... Args> inline T listMin(const T& x, const Args&... args) {
    return min(x, listMin(args...));
}

} // namespace Elaina
using namespace Elaina;

// int tau[Maxn + 5], prime[Maxn + 5];
// bool vis[Maxn + 5];
// int xi[Maxn + 5];
// inline void prelude() {
//     vis[1] = true, tau[1] = 1;
//     rep (i, 2, Maxn) {
//         if (!vis[i]) prime[++*prime] = i, tau[i] = -1;
//         for (int j = 1; j <= *prime && i * prime[j] <= Maxn; ++j) {
//             vis[i * prime[j]] = true;
//             tau[i * prime[j]] = -tau[i];
//             if (i % prime[j] == 0) break;
//         }
//     }
//     // rep (i, 1, Maxn) masdf("tau[%d] == %d\n", i, tau[i]);
//     rep (i, 1, Maxn) {
//         for (int d = 1; d * d <= i; ++d) if (i % d == 0) {
//             xi[i] += tau[d];
//             if (i != d * d) xi[i] += tau[i / d];
//         }
//         if (xi[i] != 0) printf("xi[%d] == %d\n", i, xi[i]);
//     }
// }

const int Maxn = 1e6;

bool vis[Maxn + 5];
int prime[Maxn + 5], mu[Maxn + 5];

inline void prelude() {
    vis[1] = true, mu[1] = 1;
    rep (i, 2, Maxn) {
        if (!vis[i]) prime[++*prime] = i, mu[i] = -1;
        for (int j = 1; j <= *prime && i * prime[j] <= Maxn; ++j) {
            vis[i * prime[j]] = true, mu[i * prime[j]] = -mu[i];
            if (i % prime[j] == 0) { mu[i * prime[j]] = 0; break; }
        }
    }
}

ll n, m;

inline ll work(ll n, ll m) {
    ll ret = 0;
    for (ll l = 1, r; l <= n; l = r + 1) {
        r = min(n / (n / l), m / (m / l));
        ret += (ll)sqrt(n / l) * (ll)sqrt(m / l) * (r - l + 1);
    }
    return ret;
}

signed main() {
    freopen("lost.in", "r", stdin);
    freopen("lost.out", "w", stdout);
    prelude();
    readin(n, m);
    if (n > m) swap(n, m);
    ll ans = 0;
    for (ll i = 1; i * i <= n; ++i) if (mu[i])
        ans += mu[i] * work(n / (i * i), m / (i * i));
    writln(ans);
    return 0;
}

丧钟为谁而鸣 / Harmony

  注意到 \(p\ge 20\),因此,若我们随机一次,某个答案没有被随机到的概率为 \(80\%\),如果多来几次,比如来 \(60\) 次,这个概率将会变成 \(p=(0.8)^{60}\approx 1.53249554\times 10^{-6}\). 因此,我们可以随机取一个区间中的数,然后数这个数在该区间中的出现次数。

  对于数字的统计考虑使用分块,注意在处理散块的时候要顺便将该散块的桶同时清空,总复杂度就是 \(\mathcal O(m\sqrt n\times 60)\).

/** @author __Elaina__ */

#pragma GCC optimize("Ofast")

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

#define USING_FREAD
// #define NDEBUG
#include <cassert>

namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */

#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)

typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;

template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }

#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
    static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
    return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI ((char)getchar())
#endif

template<class T> inline T readret(T x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    return f ? -x : x;
}
template<class T> inline void readin(T& x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
    readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
    if (x < 0) putchar('-'), x = -x;
    static int __stk[55], __bit = 0;
    do __stk[++__bit] = x % 10, x /= 10; while (x);
    while (__bit) putchar(__stk[__bit--] ^ 48);
    putchar(c);
}
template<class T> inline T listMax(const T& x) { return x; }
template<class T, class... Args> inline T listMax(const T& x, const Args&... args) {
    return max(x, listMax(args...));
}
template<class T> inline T listMin(const T& x) { return x; }
template<class T, class... Args> inline T listMin(const T& x, const Args&... args) {
    return min(x, listMin(args...));
}

} // namespace Elaina
using namespace Elaina;

const int Maxm = 3e4;
const int Maxn = 1e5 + 3e4 + 5;
const int Blo = 320;

// const int Maxm = 100;
// const int Maxn = 100;
// const int Blo = 1;

int a[Maxn + 5], n, m, perc;
int blef[Maxn / Blo + 5], brig[Maxn / Blo + 5], bel[Maxn + 5], bcnt;
int tag[Maxn / Blo + 5]; // the number which cover the block

int op[Maxn + 5], ql[Maxn + 5], qr[Maxn + 5], qt[Maxn + 5];
int arr[Maxn + 5], siz;

int buc[Maxn / Blo + 5][Maxn + 5];

inline void prelude() {
    sort(arr + 1, arr + siz + 1);
    siz = unique(arr + 1, arr + siz + 1) - arr - 1;
    memset(tag, 0xff, sizeof tag);

    rep (i, 1, n) a[i] = lower_bound(arr + 1, arr + siz + 1, a[i]) - arr;
    rep (i, 1, m) if (op[i] == 1) qt[i] = lower_bound(arr + 1, arr + siz + 1, qt[i]) - arr;

    for (int i = 1; (i - 1) * Blo + 1 <= n; ++i) {
        bcnt = i;
        blef[i] = (i - 1) * Blo + 1, brig[i] = min(i * Blo, n);
        rep (j, blef[i], brig[i]) bel[j] = i, ++buc[i][a[j]];
    }
}

inline void filbuc(int id, int x) {
    rep (i, blef[id], brig[id]) buc[id][a[i]] += x;
}
inline void pushdown(int id) {
    if (!~tag[id]) return ;
    rep (j, blef[id], brig[id]) {
        --buc[id][a[j]];
        ++buc[id][a[j] = tag[id]];
    }
    tag[id] = -1;
}
inline void update(int ql, int qr, int x) {
    if (bel[ql] == bel[qr]) {
        pushdown(bel[ql]);
        rep (i, ql, qr) {
            --buc[bel[ql]][a[i]];
            ++buc[bel[ql]][a[i] = x];
        }
        return ;
    }
    pushdown(bel[ql]), pushdown(bel[qr]);
    rep (i, ql, brig[bel[ql]]) {
        --buc[bel[ql]][a[i]];
        ++buc[bel[ql]][a[i] = x];
    }
    rep (i, bel[ql] + 1, bel[qr] - 1) tag[i] = x;
    rep (i, blef[bel[qr]], qr) {
        --buc[bel[qr]][a[i]];
        ++buc[bel[qr]][a[i] = x];
    }
    return ;
}
inline int query(int ql, int qr, int x) {
    int ret = 0;
    if (bel[ql] == bel[qr]) {
        pushdown(bel[ql]);
        rep (i, ql, qr) ret += (a[i] == x);
        return ret;
    }
    pushdown(bel[ql]), pushdown(bel[qr]);
    rep (i, ql, brig[bel[ql]]) ret += (a[i] == x);
    rep (i, bel[ql] + 1, bel[qr] - 1) {
        if (tag[i] == -1) ret += buc[i][x];
        else ret += (tag[i] == x) * (brig[i] - blef[i] + 1);
    }
    rep (i, blef[bel[qr]], qr) ret += (a[i] == x);
    return ret;
}

mt19937 rnd(0xcbdd1);
// inline ull regen() {
//     return ((rnd() ^ rnd() | rnd() & rnd()) & 0x7fff) << 15 | ((rnd() ^ rnd() | rnd() & rnd()) & 0x7fff);
// }
inline int gen(int l, int r) {
    return rnd() % (r - l + 1) + l;
}
unordered_map<int, bool> used;
int ans[Maxn + 5], ans_siz;
inline void solve(int ql, int qr) {
    int mxx = 0, len = qr - ql + 1;
    used.clear(), ans_siz = 0;
    rep (_, 1, 100) {
        int p = gen(ql, qr);
        if (used.count(p)) continue;
        used[p] = true;
        p = (tag[bel[p]] == -1? a[p]: tag[bel[p]]);
        int cnt = query(ql, qr, p);

        if (cnt * 100 < len * perc) continue;

        if (cnt > mxx) ans[ans_siz = 1] = p, mxx = cnt;
        else if (cnt == mxx) ans[++ans_siz] = p;

        // if (ans_siz == 100 / perc) break;

        if ((int)used.size() >= 60) break;
    }
    sort(ans + 1, ans + ans_siz + 1);
    ans_siz = unique(ans + 1, ans + ans_siz + 1) - ans - 1;
    writln(ans_siz, ' ');
    rep (i, 1, ans_siz) writln(arr[ans[i]], ' ');
    Endl;
}

inline void work() {
    rep (i, 1, m) {
        if (op[i] == 1) update(ql[i], qr[i], qt[i]);
        else solve(ql[i], qr[i]);
    }
}

signed main() {
    freopen("harmony.in", "r", stdin);
    freopen("harmony.out", "w", stdout);
    readin(n, m, perc);
    rep (i, 1, n) readin(a[i]), arr[++siz] = a[i];
    rep (i, 1, m) {
        readin(op[i], ql[i], qr[i]);
        if (op[i] == 1) readin(qt[i]), arr[++siz] = qt[i];
    }
    prelude();
    work();
    return 0;
}

老人与海 / Dignity

  注意每种武器的 OGF 为 \(\displaystyle \frac{1}{1-x^{a_i}}\),因此

\[f(T)=[x^T]\prod_{i=1}^n \frac{1}{1-x^{a_i}} \]

  但是他们全是分式,不是特别好处理,令 \(W=\lcm(a_i)\),那么,我们可以将原式写成:

\[f(T)=[x^T]\frac{1}{(1-x^W)^n}\prod_{i=1}^n\frac{1-x^W}{1-x^{a_i}} \\ =[x^T]\brak{\sum_{i=0}^{+\infty}x^{iW}}^n\prod_{i=1}^n\brak{\sum_{j=0}^{(W/a_i)-1}x^{j\times a_i}} \]

  这个多项式考虑分成两个部分:\(\displaystyle \brak{\sum_{i=0}^{+\infty}x^{iW}}^n\) 和 \(\displaystyle \prod_{i=1}^n\brak{\sum_{j=0}^{(W/a_i)-1}x^{j\times a_i}}\),前半部分只有 \(x^{iW}\) 项,并且其系数为 \(\displaystyle {n+i-1\choose i-1}\),后半部分是一个次数很低的多项式,可以直接做多项式乘法得到,记前者为多项式 \(Q\),后者为多项式 \(P\).

  于是,可以将 \(T=kW+r\),记 \(f(T)=G(k,r)\),并且对于 \(G(k,r)\),我们有

\[G(k,r)=\sum_{i=0}^{k}q((k-i)W)+p(iW+r)=\sum_{i=0}^k{n+k-i-1\choose n-1}p(iW+r) \]

  在原问题中,我们要找到最小的 \(T\) 使得 \(f(T)\ge h_i\),只需要对每个 \(\bmod W\) 的余数都做一次二分即可,因为显然当 \(r\) 固定时,\(G(k,r)\) 随 \(k\) 单增。

/** @author __Elaina__ */

#pragma GCC optimize("Ofast")

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

#define USING_FREAD
// #define NDEBUG
#include <cassert>

namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */

#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)

typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;

template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }

#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
    static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
    return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI ((char)getchar())
#endif

template<class T> inline T readret(T x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    return f ? -x : x;
}
template<class T> inline void readin(T& x) {
    x = 0; int f = 0; char c;
    while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
    if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
    readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
    if (x < 0) putchar('-'), x = -x;
    static int __stk[55], __bit = 0;
    do __stk[++__bit] = x % 10, x /= 10; while (x);
    while (__bit) putchar(__stk[__bit--] ^ 48);
    putchar(c);
}
template<class T> inline T listMax(const T& x) { return x; }
template<class T, class... Args> inline T listMax(const T& x, const Args&... args) {
    return max(x, listMax(args...));
}
template<class T> inline T listMin(const T& x) { return x; }
template<class T, class... Args> inline T listMin(const T& x, const Args&... args) {
    return min(x, listMin(args...));
}

} // namespace Elaina
using namespace Elaina;

const int Maxn = 1e5;
const ll inf = 1ll << 60;

int a[Maxn + 5], n, W = 1, q;

int p[Maxn + 5], m;

inline void input() {
    readin(n);
    rep (i, 1, n) {
        readin(a[i]);
        int g = __gcd(a[i], W);
        W = W / g * a[i];
    }
    // masdf("W == %d\n", W);
}

int tmp[Maxn + 5];
inline void solveP() {
    p[0] = 1, m = 1;
    rep (i, 1, n) {
        int mxp = 0;
        repf (j, 0, m) if (p[j])
            repf (t, 0, W / a[i])
                tmp[j + t * a[i]] += p[j], chkmax(mxp, j + t * a[i]);
        chkmax(m, mxp + 1);
        memcpy(p, tmp, m << 2);
        memset(tmp, 0, m << 2);
    }
    // repf (i, 0, m) masdf("%d ", p[i]); Endl;
}

inline ll C(ll n, ll m) {
    ll ret = 1;
    for (int i = 1; i <= m; ++i, --n)
        ret *= n;
    rep (i, 1, m) ret /= i;
    return ret;
}

inline ll check(ll k, int r, const ll& tar) {
    ll fun_val = 0;
    for (int i = 0; ; ++i) {
        int now = i * W + r;
        if (now >= m) break;
        if (!p[now]) continue; // useless
        // to avoid ll leak
        ll res = tar - fun_val;
        repf (t, 1, n) res *= t;
        res /= p[now];
        repf (t, 1, n) {
            if (n + k - i - t == 0) { res = inf; break; }
            res /= (n + k - i - t);
        }
        if (res <= 0) return true;

        fun_val += C(n + k - i - 1, n - 1) * p[now];
    }
    return fun_val >= tar;
}

signed main() {
    freopen("dignity.in", "r", stdin);
    freopen("dignity.out", "w", stdout);
    input();
    solveP();
    readin(q);
    while (q--) {
        ll h, ans = inf; readin(h);
        repf (r, 0, W) {
            ll pl = 0, pr = min((100 * h - r) / W, (ans - r) / W);
            if (!check(pr, r, h)) continue;
            ll resk = -1;
            for (ll mid = pl + pr >> 1; pl <= pr; mid = pl + pr >> 1)
                if (check(mid, r, h)) resk = mid, pr = mid - 1;
                else pl = mid + 1;
            if (~resk) chkmin(ans, resk * W + r);
        }
        if (ans == inf) puts("What a pity!");
        else writln(ans);
    }
    return 0;
}

标签:__,有人,const,int,题解,打树套,ans,inline,define
来源: https://www.cnblogs.com/Arextre/p/16030755.html