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题就是整除分块,是不是有点抽象?
数论题一般考虑具体的公式
我们先观察式子
整理得
考虑 K 的上界,为 \(\big \lceil \frac{B}{A} \big \rceil \le 10^9\),显然不能逐一枚举 K,还需要化简,
如果 K 固定,那么观察上式,易得
为了让 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;
}

浙公网安备 33010602011771号