AtCoder Regular Contest 150补题

AtCoder Regular Contest 150

A. Continuous 1

知识点:简单题
复杂度:\(O(n)\)

当一个区间合法,那么必定区间长度为 k,并且区间内无0,并且1的个数等于所有的1的总和
这个使用个前缀和即可\(O(1)\)维护


#define rep(i,l,r) for(int i=l,_##i=r;i<=_##i;i++)
#define per(i,l,r) for(int i=r,_##i=l;i>=_##i;i--)
#define ll long long
#define fi first
#define se second
#define endl '\n'
#define pll pair<ll,ll>
#define pii pair<int,int>
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T> >;
const int N = 3e5 + 5;

int n, m, k;
char s[N];

int pre[N][2];

void solve()
{
    cin >> n >> k >> (s + 1);
    int sum = 0;
    rep(i, 1, n) if (s[i] == '1') sum++;
    int cnt = 0;
    rep(i, 1, n)
    {
        rep(j, 0, 1) pre[i][j] = pre[i - 1][j];
        if (s[i] == '0') pre[i][0]++;
        else if (s[i] == '1') pre[i][1]++;
        if (i >= k)
        {
            if (pre[i][0] - pre[i - k][0] == 0 && pre[i][1] - rep[i - k][1] == sum)
                cnt++;
        }
    }
    cout << (cnt == 1 ? "Yes" : "No") << endl;
}

B. Make Divisible

知识点:整除分块
复杂度:\(O(\sqrt{B})\)

没怎么打过Atcoder,但是B题就是整除分块,是不是有点抽象?

数论题一般考虑具体的公式
我们先观察式子

\[\frac{B+Y}{A+X}=K \]

整理得

\[B+Y=(A+X)K \]

考虑 K 的上界,为 \(\big \lceil \frac{B}{A} \big \rceil \le 10^9\),显然不能逐一枚举 K,还需要化简,

如果 K 固定,那么观察上式,易得

\[B \le (A+X)K \Rightarrow \bigg \lceil \frac{B}{K} \bigg \rceil \le A+X \]

为了让 X 取到最小值,显然 \(X=max(0,\big \lceil \frac{B}{K} \big \rceil - A)\),
整理得到 \(X=max(0,\big \lfloor \frac{B-1}{K} \big \rfloor +1-A)\)

观察得到 \(\big \lfloor \frac{B-1}{K} \big \rfloor\) 只有 \(\sqrt{B}\) 个取值,所以我们可以直接枚举 X


#define rep(i,l,r) for(int i=l,_##i=r;i<=_##i;i++)
#define per(i,l,r) for(int i=r,_##i=l;i>=_##i;i--)
#define ll long long
#define fi first
#define se second
#define endl '\n'
#define pll pair<ll,ll>
#define pii pair<int,int>
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T> >;

ll a, b;
void solve()
{
    cin >> a >> b;
    if (a >= b) cout << a - b << endl;
    else if (b % a == 0) cout << 0 << endl;
    else
    {
        ll ans = a - b % a;
        ll lim = b - 1;
        for (ll l = 1, r; l <= lim; l = r + 1)
        {
            r = lim / (lim / l);
            ll x = max(0ll, lim / l + 1 - a);
            ll y = (b + a + x - 1) / (a + x) * (a + x) - b;
            ans = min(ans, x + y);
        }
        cout << ans << endl;
    }
}

C. Path and Subsequence

知识点:dp
复杂度:\(O(nlogn)\)

不会,看这位大佬的题解补的
很抽象的dij,不过细细推敲确实又很自然


#define rep(i,l,r) for(int i=l,_##i=r;i<=_##i;i++)
#define per(i,l,r) for(int i=r,_##i=l;i>=_##i;i--)
#define ll long long
#define fi first
#define se second
#define endl '\n'
#define pll pair<ll,ll>
#define pii pair<int,int>
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T> >;
const int N = 1e5 + 5;

int n, m, k;
vc<int> h[N];
int a[N], b[N], d[N];
bool st[N];

void solve()
{
    cin >> n >> m >> k;
    rep(i, 1, m)
    {
        int u, v;
        cin >> u >> v;
        h[u].pb(v);
        h[v].pb(u);
    }
    rep(i, 1, n) cin >> a[i], d[i] = inf;
    rep(i, 1, k) cin >> b[i];
    d[1] = (a[1] == b[1] ? 1 : 0);
    priority_queue<pii, vc<pii>, greater<pii> > p;
    p.push({ d[1], 1 });
    while (p.size())
    {
        auto u = p.top(); p.pop();
        if (st[u.se]) continue;
        st[u.se] = true;
        for (auto v : h[u.se])
        {
            int x = d[u.se] + bool(d[u.se] < k && a[v] == b[d[u.se] + 1]);
            if (x < d[v])
            {
                d[v] = x;
                p.push({ d[v], v });
            }
        }
    }
    cout << YN(d[n] == k) << endl;
}

D. Removing Gacha

知识点:期望
复杂度:\(O(n)\)

还是这位大佬的题解,太妙了

和的期望等于期望的和,这句翻译一下就是,我对于所有点染完的期望,等于每个点被染色期望的和
而对于一点被染色的期望次数,我们只需要观察一条链即可,
因为当一个点不需要再被染色时,当且仅当根结点到他的这一条链都被染色
而至于为啥能等效模型成染多少次才能染完一条链的n个节点,我的观点是在计算期望时,
这一条链上每一个点都可以视为该链的最后一个点,因此可以与题面中长度为n的链的末尾的那个节点等效看待
所以我们求出上面的模型的期望次数的总和取平均即可


#define rep(i,l,r) for(int i=l,_##i=r;i<=_##i;i++)
#define per(i,l,r) for(int i=r,_##i=l;i>=_##i;i--)
#define ll long long
#define fi first
#define se second
#define endl '\n'
#define pll pair<ll,ll>
#define pii pair<int,int>
template<class T> using vc = vector<T>;
template<class T> using vvc = vc<vc<T> >;
const int N = 2e5 + 5;

int n, m, k;

ll inv[N];//逆元
ll pre[N];
vc<int> h[N];
ll ans;
int d[N];

void dfs(int u)
{
    ans = (ans + pre[d[u]]) % mod;
    for (auto v : h[u])
    {
        d[v] = d[u] + 1;
        dfs(v);
    }
}

void solve()
{
    cin >> n;
    inv[1] = 1;
    rep(i, 2, n) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    rep(i, 1, n) pre[i] = (inv[i] + pre[i - 1]) % mod;
    rep(i, 2, n)
    {
        int f; cin >> f;
        h[f].pb(i);
    }
    dfs(d[1] = 1);
    cout << ans << endl;
}
posted @ 2022-11-20 00:08  Apricity_chen  阅读(35)  评论(0)    收藏  举报