A. Pride
如果有
1
答案是
如果
否则求出最短区间
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 2005;
int n, ans, a[MAXN];
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = ans = Read();
int cnt = 0, cur = 0;
for (int i = 1; i <= n; i ++)
cnt += (a[i] = Read()) == 1, cur = __gcd(cur, a[i]);
if (cnt)
return printf("%d\n", n - cnt), 0;
if (cur ^ 1)
return puts("-1"), 0;
for (int i = 1; i <= n; i ++)
for (int j = i, x = 0; j <= n; j ++)
if ((x = __gcd(x, a[j])) == 1)
ans = min(ans, j - i - 1), j = n;
return printf("%d\n", ans + n), 0;
}
B. Gluttony
将 a 按照大小关系循环移位一次。
证明:考虑一个子集,如果不包含最小数,那么其和一定增加了,否则其补集和增加了。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 25;
int n, b[MAXN];
pii a[MAXN];
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read();
for (int i = 1; i <= n; i ++)
a[i] = mp(Read(), i);
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i ++)
b[a[i % n + 1].yy] = a[i].xx;
for (int i = 1; i <= n; i ++)
printf("%d%c", b[i], i == n ? '\n' : ' ');
return 0;
}
C. Envy
首先权值不同的边可以分开考虑。
离线,用并查集维护之前的边的状态,然后对于一种权值的所有询问,判断是否成环,然后撤销即可。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 500005;
int n, m, q, val, top, f[MAXN], u[MAXN], v[MAXN], w[MAXN], siz[MAXN], sta[MAXN];
vector <pii> edg[MAXN], qry[MAXN];
bool ans[MAXN];
inline int Find(int x)
{
while (x ^ f[x])
x = f[x];
return x;
}
inline bool Merge(int x, int y)
{
x = Find(x), y = Find(y);
if (x == y)
return false;
if (siz[x] > siz[y])
swap(x, y);
f[x] = y, siz[y] += siz[x];
sta[++ top] = x;
return true;
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(), m = Read();
for (int i = 1; i <= m; i ++)
u[i] = Read(), v[i] = Read(), w[i] = Read(), edg[w[i]].pb(mp(u[i], v[i])), val = max(val, w[i]);
q = Read();
for (int i = 1; i <= q; ans[i ++] = true)
for (int c = Read(), x; c; c --)
x = Read(), qry[w[x]].pb(mp(i, x));
for (int i = 1; i <= n; i ++)
f[i] = i, siz[i] = 1;
for (int i = 1; i <= val; i ++)
{
for (int l = 0, r = 0; l < qry[i].size(); l = r)
{
while (r < qry[i].size() && qry[i][r].xx == qry[i][l].xx)
r ++;
for (int j = l; j < r; j ++)
if (!Merge(u[qry[i][j].yy], v[qry[i][j].yy]))
ans[qry[i][j].xx] = false, j = r;
while (top)
{
int x = sta[top --];
siz[f[x]] -= siz[x], f[x] = x;
}
}
for (auto e : edg[i])
Merge(e.xx, e.yy);
top = 0;
}
for (int i = 1; i <= q; i ++)
puts(ans[i] ? "YES" : "NO");
return 0;
}
D. Sloth
叉姐给的做法:
状态有
求出子树内和子树外的答案即可。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 500005;
struct Node
{
int a[2][2];
Node(int x = 0, int y = 0, int w = 0, int z = 0)
{
a[0][0] = x, a[0][1] = y, a[1][0] = w, a[1][1] = z;
}
inline Node Trans()
{
return Node(a[1][0], a[0][0] + a[1][1], a[0][0], a[0][1]);
}
Node operator + (const Node &b) const
{
Node c;
for (int i = 0; i < 2; i ++)
for (int j = 0; j < 2; j ++)
for (int k = 0; k + i < 2; k ++)
for (int l = 0; l + j < 2; l ++)
c.a[k + i][l + j] += a[i][j] * b.a[k][l];
return c;
}
} f[MAXN], g[MAXN];
vector <int> adj[MAXN];
int n, siz[MAXN];
inline void DFS(int x, int p)
{
siz[x] = 1, f[x].a[0][0] = 1;
if (p)
adj[x].erase(find(adj[x].begin(), adj[x].end(), p));
for (auto y : adj[x])
DFS(y, x), f[x] = f[x] + f[y].Trans(), siz[x] += siz[y];
}
inline void DP(int x, int p)
{
vector <Node> pre;
Node cur(1, 0, 0, 0);
if (p)
pre.pb(g[x].Trans());
else
pre.pb(cur);
for (auto y : adj[x])
pre.pb(pre.back() + f[y].Trans());
for (int i = adj[x].size() - 1; ~i; i --)
g[adj[x][i]] = pre[i] + cur, cur = cur + f[adj[x][i]].Trans(), DP(adj[x][i], x);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read();
if (n & 1)
return puts("0"), 0;
for (int i = 1, x, y; i < n; i ++)
x = Read(), y = Read(), adj[x].pb(y), adj[y].pb(x);
DFS(1, 0);
DP(1, 0);
LL ans = 0;
for (int i = 2; i <= n; i ++)
if (f[i].a[1][0] == 1 && g[i].a[1][0] == 1)
ans += 1LL * siz[i] * (n - siz[i]);
else
ans += 1LL * (f[i].a[0][0] + f[i].a[1][1]) * (g[i].a[0][0] + g[i].a[1][1]);
cout << ans << endl;
return 0;
}
E. Lust
记
bi
表示
i
被减了
E(∏∑bi=k(ai−bi))=k!nk∏∑bi=kai−bibi! 。
用EGF推,有下式:
F(x)=∏ni=1∑j≥0xj(ai−j)j!=∏ni=1(ai−x)ex=enx∏ni=1(ai−x)
令 G(x)=∏ni=1(ai−x)=∑ni=0cixi ,可以暴力求出 cj (也可以分治FFT),有:
[xk]F(x)=∑ni=0cink−i(k−i)! 。
所以 E=∑ni=0ci∏kj=k−i+1jni 。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 5005;
const int mod = 1e9 + 7;
int n, m, a[MAXN], f[MAXN];
inline int Qow(int x, int y)
{
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod)
if (y & 1)
r = 1LL * r * x % mod;
return r;
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(), m = Read(), f[0] = 1;
for (int i = 1; i <= n; i ++)
{
a[i] = Read();
for (int j = i; j; j --)
f[j] = (1LL * f[j] * a[i] - f[j - 1] + mod) % mod;
f[0] = 1LL * f[0] * a[i] % mod;
}
int cur = 1, bas = Qow(n, mod - 2), ret = 0;
for (int i = 0; i <= n; i ++)
ret = (1LL * cur * f[i] + ret) % mod, cur = 1LL * cur * bas % mod * (m - i) % mod;
return printf("%d\n", (f[0] - ret + mod) % mod), 0;
}