Tech OIers save the world|

Lucky_Luo

园龄:1年8个月粉丝:7关注:5

abc321记录

SuntoryProgrammingContest2023(AtCoder Beginner Contest 321) - AtCoder

D

题意:给定常数 k 和长度为 n 的数组 a 和长度为 m 的数组 b,求 i=1nj=1mmin{ai+bj,k}

数据范围:n,m2×105

tag : 二分 前缀和

枚举 ai,在 b 上二分 kai,找到的位置前面的前缀和后面的全是 k

E

题意:多个询问,每个询问给定 n 个点,根为 1 的一棵树,节点 u 的父亲为 u2,求与节点 v 距离为 k 的点的个数。

数据范围:kn1018

tag : 完全二叉树 树形dp

考虑类似换根dp的过程,设 g(u,k)u 子树中距离为 k 的点,这在完全二叉树上显然可以快速计算,计算当前点的答案 f(u,k) 时实际上是父亲的答案减去在自己子树里多算的部分,{f(u,k)=g(u,k)+f(fa,k1)g(u,k2)f(1,k)=g(1,k),因为树高 O(logn),直接向上暴力计算,注意最底层不满的 corner case 。

F

题意:n 个操作,每个操作在可重集 S 中加入或删除一个元素 k ,求每次操作后选取一个子集 S 使得 kS=m 的方案数。

数据范围:n,m5000

tag : 背包 线段树分治

回退背包板子,注意加入顺序从大到小,回退顺序从小到大。但是赛时线段树分治直接艹过去了

G

题意:给定长度为 m,值域为 [1,n] 的数组 a,b,对于每个 i 都对应一个互不相同的 j,代表在图上编号为 ai 的点向编号为 bj 的点连一条双向边,求在所有的连边方式中图的连通块个数的期望。

数据范围:m105,n17

tag : 状压dp,容斥

赛后补题,参考了一定的lg题解。

显然总的连边方案数是确定的 m!,那么考虑拆分每个连通块的贡献,计算每个连通块在所有连边方式中出现的次数。

注意到 n17,考虑状压,设 fS 表示点集 S 只有内部连边并形成至少一个连通块的方案数,gS 表示点集 S 只有内部连边并形成恰好一个连通块的方案数,显然 f 是易求的,设 cntaS,cntbS 分别表示 S 的元素在 a,b 中出现的次数,当 cntaS=cntbS 时,S 内部可以随便连边,否则,必然有一条边连接 S 内部的点和外部的点,所以有:fS=[cntaS=cntbS]×cntaS!

接下来考虑通过 f 求出 g,显然可以容斥:S 形成恰好一个连通块的方案数等于形成至少一个连通块的方案数减形成多于一个连通块的方案数。而多于一个连通块的方案数显然等于一个子集形成恰好一个连通块的方案数乘以它关于 S 的补集形成至少一个连通块的方案数。这就可以写成转移方程了:gS=fSTSgT×fST

求完 g ,统计答案时还要乘上 S 外部随便连边的方案数:ans=gS×(mcntaS)!m!

贴个代码

#include <bits/stdc++.h>
#define pb push_back
#define rg register
#define il inline
using namespace std;
typedef long long ll;
//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 1<<17, mo = 998244353;
int i, j, k, l, r, m, n, ans;
int a[N], b[N], fc[N], f[N], g[N];
il int read()
{
    int x = 0, flag = 1;
    char ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') flag = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x * flag;
}
int qp(int a, int b=mo-2)
{
	int res = 1;
	for (a%=mo ; b; b>>=1, a=1ll*a*a%mo) if (b&1) res = 1ll * res * a % mo;
	return res;
}
signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0), cout.tie(0);
	n = read(), m = read();
	for (fc[0]=i=1; i<=m; i++) fc[i] = 1ll * i * fc[i-1] % mo;
	for (i=1; i<=m; i++) a[read()-1]++;
	for (i=1; i<=m; i++) b[read()-1]++;
	for (k=1; k<(1<<n); k++)
	{
		int sa = 0, sb = 0, p = -1;
		for (i=0; i<n; i++) if (k>>i&1) sa += a[i], sb += b[i], p = ~p ? p : i;
		if (sa != sb) continue;
		g[k] = f[k] = fc[sa];
		for (i=k; i; i=i-1&k) if (i!=k && i>>p&1) g[k] = (g[k] - 1ll * g[i] * f[i^k] % mo + mo) % mo;
		ans = (ans + 1ll * g[k] * fc[m-sa] % mo) % mo;
	}
	printf("%d", 1ll*ans*qp(fc[m])%mo);
    return 0;
}
posted @   Lucky_Luo  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 Force Theme Audio artist
  2. 2 Cornfield Chase Audio artist
  3. 3 Time Audio artist
Force Theme - Audio artist
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.