A Car Show
题意:给定长度为 的序列 ,其中 ,求有多少个连续子区间包含 中每个数。。
解法:使用双指针即可。时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
const int N = 100000;
int cnt[N + 5], a[N + 5];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
long long ans = 0;
for (int i = 1; i <= n;i++)
scanf("%d", &a[i]);
int now = 0;
for (int l = 1, r = 1; l <= n;l++)
{
while (r <= n && now < m)
{
if(!cnt[a[r]])
now++;
cnt[a[r]]++;
r++;
}
if (now == m)
ans += n - r + 2;
cnt[a[l]]--;
if (!cnt[a[l]])
now--;
}
printf("%lld", ans);
return 0;
}
B Two Frogs
题意:有一长度为 的数轴和 个青蛙,初始均在 号点,在第 号点两个青蛙都以等概率跳到 号点,问两青蛙以相同次数跳跃抵达 号点的概率。。
解法:计算出单个青蛙的答案即可。设 为在 号点,还需要跳跃 次抵达 号点的概率,则答案为 。其转移非常显然:。使用后缀和优化即可,整体复杂度 。
#include <bits/stdc++.h>
using namespace std;
const int N = 8000;
const long long mod = 998244353;
long long power(long long a, long long x)
{
long long ans = 1;
while(x)
{
if (x & 1)
ans = ans * a % mod;
a = a * a % mod;
x >>= 1;
}
return ans;
}
int a[N + 5], f[N + 5][N + 5], suf[N + 5][N + 5];
long long inv[N + 5];
int main()
{
int n;
scanf("%d", &n);
inv[1] = 1;
for (int i = 2; i <= n; i++)
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
for (int i = 1; i <= n;i++)
scanf("%d", &a[i]);
f[n][0] = suf[n][0] = 1;
for (int i = n - 1; i >= 1; i--)
{
suf[i][0] = suf[i + 1][0];
for (int j = 1; j <= n; j++)
f[i][j] = 1ll * (suf[i + 1][j - 1] - suf[i + a[i] + 1][j - 1] + mod) % mod * inv[a[i]] % mod,
suf[i][j] = (suf[i + 1][j] + f[i][j]) % mod;
}
long long ans = 0;
for (int i = 1; i <= n; ++i)
ans = (ans + 1ll * f[1][i] * f[1][i] % mod) % mod;
printf("%lld", ans);
return 0;
}