5.28 题解
A
转化成
枚举
#include <cstdio>
#include <cstring>
#define M 10000007
int c, k, a[150];long long n, q = 1, f[150][150];
long long F(int x, int y, bool l)
{
if(!x) return y == k;
if(!l && ~f[x][y]) return f[x][y];long long q = 0;
for(int i = 0, j = l ? a[x] : 1;i <= j;++i)
q += F(x - 1, y + i, l && i == j);
if(!l) f[x][y] = q;return q;
}
long long G(long long n)
{
memset(f, -1, sizeof f);c = 0;
while(n) a[++c] = n & 1, n >>= 1;
return F(c, 0, 1);
}
long long P(long long x, long long y)
{
long long q = 1;
for(;y;y >>= 1, x = x * x % M)
if(y & 1) q = q * x % M;
return q;
}
int main()
{
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
scanf("%lld", &n);
for(k = 1;k <= 65;++k)
q = q * P(k, G(n)) % M;
printf("%lld", q);
fclose(stdin);fclose(stdout);
return 0;
}
B
不会。
C
整体二分套二维树状数组。
令询问
考虑对某组
若
否则其答案等于
还原
二维树状数组维护
#include <cstdio>
struct S{int o, l1, l2, r1, r2, k, i;}a[500050], q1[500050], q2[500050];
int n, q, m, z[500050], c[550][550];
void M(int x, int y, int k)
{
for(;x <= n;x += x & -x)
for(int i = y;i <= n;i += i & -i)
c[x][i] += k;
}
int Q(int x, int y)
{
int q = 0;
for(;x;x &= x - 1)
for(int i = y;i;i &= i - 1)
q += c[x][i];
return q;
}
void D(int l, int r, int s, int t)
{
if(l > r) return;
if(s == t)
{
for(int i = l;i <= r;++i)
if(a[i].o == 2) z[a[i].i] = s;
return;
}
int m = s + t >> 1, c1 = 0, c2 = 0;
for(int i = l, o;i <= r;++i)
{
if(a[i].o & 1)
{
if(a[i].k <= m)
M(a[i].l1, a[i].l2, 1), q1[++c1] = a[i];
else
q2[++c2] = a[i];
}
else
{
o = Q(a[i].r1, a[i].r2) - Q(a[i].l1 - 1, a[i].r2) - Q(a[i].r1, a[i].l2 - 1) + Q(a[i].l1 - 1, a[i].l2 - 1);
if(o >= a[i].k)
q1[++c1] = a[i];
else
a[i].k -= o, q2[++c2] = a[i];
}
}
for(int i = 1;i <= c1;++i) if(q1[i].o & 1) M(q1[i].l1, q1[i].l2, -1);
for(int i = 1;i <= c1;++i) a[l + i - 1] = q1[i];
for(int i = 1;i <= c2;++i) a[l + c1 + i - 1] = q2[i];
D(l, l + c1 - 1, s, m);D(l + c1, r, m + 1, t);
}
int main()
{
// freopen("c.in", "r", stdin);
// freopen("c.out", "w", stdout);
scanf("%d%d", &n, &q);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j)
a[++m] = (S){1, i, j, 0, 0, 0, 0}, scanf("%d", &a[m].k);
for(int i = 1;i <= q;++i)
a[++m] = (S){2, 0, 0, 0, 0, 0, i}, scanf("%d%d%d%d%d", &a[m].l1, &a[m].l2, &a[m].r1, &a[m].r2, &a[m].k);
D(1, m, 1, 1e9);
for(int i = 1;i <= q;++i)
printf("%d\n", z[i]);
return 0;
}
D
虚树 DP。
回收路径树就是最短路树,直接建出来。
具体地,以
设
被标记的区域就是以回收区域为关键点集建的虚树,每次询问直接建出来。
具体地,把关键点集按 DFS 序排序,然后关键点集与其相邻每两项的 LCA 即为标记区域,
标记区域之间按原树祖先关系连边,边权为原树上两点间边权和。
在建出的虚树上跑 DP。设
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define P pair<int, int>
using namespace std;
const int N = 1e9;
struct G
{
struct E{int v, w, t;}e[200050];int c, h[50050];
void A(int u, int v, int w) {e[++c] = (E){v, w, h[u]};h[u] = c;}
}A, T, V;
bool t[50050], e[50050];P r[50050];
int n, m, s, p, O, a[50050], z[50050], b[50050], d[50050], f[50050][20], g[50050], W[50050], o[50050];
priority_queue<P, vector<P>, greater<P> > q;
bool C(int x, int y) {return b[x] < b[y];}
void D(int u)
{
b[u] = ++p;
for(int i = T.h[u], v;i;i = T.e[i].t)
{
d[v = T.e[i].v] = d[u] + 1;
W[v] = W[f[v][0] = u] + T.e[i].w;
for(int j = 1;f[v][j - 1];++j)
f[v][j] = f[f[v][j - 1]][j - 1];D(v);
}
}
int L(int x, int y)
{
if(d[x] < d[y]) swap(x, y);
while(d[x] > d[y]) x = f[x][__lg(d[x] - d[y])];
if(x == y) return x;
for(int k = __lg(d[x]);k >= 0;--k)
if(f[x][k] != f[y][k]) x = f[x][k], y = f[y][k];
return f[x][0];
}
void F(int u)
{
o[u] = 0;
for(int i = V.h[u], v;i;i = V.e[i].t)
F(v = V.e[i].v), o[u] += min(V.e[i].w, t[v] ? N : o[v]);
}
int main()
{
// freopen("d.in", "r", stdin);
// freopen("d.out", "w", stdout);
scanf("%d%d%d%d", &n, &m, &s, &O);
for(int i = 0, u, v, w;i < m;++i)
scanf("%d%d%d", &u, &v, &w), A.A(u, v, w), A.A(v, u, w);
memset(g, 0x3f, sizeof g);q.push(P(g[s] = 0, s));
while(!q.empty())
{
int u = q.top().second;q.pop();
if(!e[u])
{
e[u] = 1;
for(int i = A.h[u], v;i;i = A.e[i].t)
if(g[v = A.e[i].v] > g[u] + A.e[i].w || g[v] == g[u] + A.e[i].w && r[v].first > u)
q.push(P(g[v] = g[r[v].first = u] + A.e[i].w, v)), r[v].second = A.e[i].w;
}
}
for(int i = 1;i <= n;++i) if(r[i].first) T.A(r[i].first, i, r[i].second);D(s);
for(int i = 0, r, k, c = 0;i < O;++i)
{
scanf("%d%d", &r, &k);
if(r)
{
for(int j = 0;j < c;++j) V.h[z[j]] = 0;V.c = c = 0;
for(int j = 0;j < k;++j) scanf("%d", a + j);a[k++] = s;sort(a, a + k, C);z[c++] = a[0];
for(int j = 1;j < k;++j) z[c++] = L(a[j], a[j - 1]), z[c++] = a[j];sort(z, z + c, C);c = unique(z, z + c) - z;
for(int j = 1, l;j < c;++j) l = L(z[j], z[j - 1]), V.A(l, z[j], W[z[j]] - W[l]);bool U = 1;
for(int j = 0;j < c;++j) if(t[z[j]]) {U = 0;break;}if(U) {puts("-1");continue;}
F(z[0]);printf("%d\n", o[z[0]]);
}
else
{
for(int j = 0, x;j < k;++j)
scanf("%d", &x), t[x] ^= 1;
}
}
return 0;
}
无返回值函数必须是 void 型的
分类:
未分类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具