首页 > 其他分享 >2023冲刺国赛模拟20

2023冲刺国赛模拟20

时间:2023-06-18 10:24:22浏览次数:45  
标签:typedef 20 int long maxn 国赛 2023 return first

2023冲刺国赛模拟20

越来越废物了。

A. 树染色

\(f_{x, 1 / 0}\) 表示考虑 \(x\) 子树内,第一条链为黑色/白色,不考虑第一条链在子树外方案数的答案。

转移枚举第一条链是哪个,用组合数给各个子树的链定序。

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 5e5 + 55, mod = 998244353;
int qpow(int x, int y){
	int ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
int n, head[maxn], tot;
struct edge{int to, net, a, b;}e[maxn << 1 | 1];
void add(int u, int v, int a, int b){
	e[++tot] = {v, head[u], a, b};
	head[u] = tot;
}
int fac[maxn], ifac[maxn];
int c(int n, int m){
	return 1ll * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
int f[maxn][2], dep[maxn], cnt[maxn];
void solve(int x, int fa){
	int sp = 1, base = 1; 
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to; if(v == fa)continue;
		dep[v] = dep[x] + 1; 
		solve(v, x); 
		cnt[x] += cnt[v];
		base = 1ll * base * ifac[cnt[v]] % mod;
		f[v][0] = 1ll * f[v][0] * e[i].a % mod;
		f[v][1] = 1ll * f[v][1] * e[i].b % mod;
		sp = 1ll * sp * (f[v][0] + f[v][1]) % mod * dep[x] % mod;
	}
	for(int i = head[x]; i; i = e[i].net){
		int v = e[i].to; if(v == fa)continue;
		int tmp = 1ll * sp * qpow(1ll * (f[v][0] + f[v][1]) % mod * dep[x] % mod, mod - 2) % mod;
		f[x][0] = (f[x][0] + 1ll * f[v][0] * tmp % mod * base % mod * fac[cnt[v]] % mod * fac[cnt[x] - cnt[v]] % mod * c(cnt[x] - 1, cnt[v] - 1)) % mod;
		f[x][1] = (f[x][1] + 1ll * f[v][1] * tmp % mod * base % mod * fac[cnt[v]] % mod * fac[cnt[x] - cnt[v]] % mod * c(cnt[x] - 1, cnt[v] - 1)) % mod;
	}
	if(!cnt[x])f[x][0] = f[x][1] = cnt[x] = 1;
}
int main(){
	freopen("treecolor.in","r",stdin);
	freopen("treecolor.out","w",stdout);
	n = read(); 
	for(int i = 1; i < n; ++i){
		int x = read(), y = read(), a = read(), b = read(); 
		add(x, y, a, b); add(y, x, a, b);
	}
	fac[0] = ifac[0] = 1; for(int i = 1; i <= n; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
	ifac[n] = qpow(fac[n], mod - 2); for(int i = n - 1; i >= 1; --i)ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
	dep[1] = 1; solve(1, 0); 
	printf("%d\n",(f[1][0] + f[1][1]) % mod);
	return 0;
}

B. 关路灯

预处理转向点,发现对于每个点出发,只有 \(log\) 个转向点。

对其扫描线。

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, ll> pil;
typedef pair<ll, int> pli;
int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 5e5 + 55;
int n, m, a[maxn], st[20][maxn];
ll ans[maxn];
vector<pii>ql[maxn], qr[maxn];
vector<pil>pl[maxn], pr[maxn];
int queryl(int x, int lim){
	for(int i = 18; i >= 0; --i)if(x - (1 << i) + 1 >= 1 && st[i][x - (1 << i) + 1] < lim)x -= (1 << i);
	return x;
}
int queryr(int x, int lim){
	for(int i = 18; i >= 0; --i)if(x + (1 << i) - 1 <= n && st[i][x] <= lim)x += (1 << i);
	return x;
}
pli operator + (const pli &x, const pli &y){return pli(x.first + y.first, x.second + y.second);}
pli operator - (const pli &x, const pli &y){return pli(x.first - y.first, x.second - y.second);}
struct BIT{
	pli t[maxn];
	int lowbit(int x){return x & -x;}
	void add(int x, pli val){while(x <= n)t[x] = t[x] + val, x += lowbit(x);}
	pli query(int x){
		pli ans;
		while(x){ans = ans + t[x]; x -= lowbit(x);}
		return ans;
	}
	pli query(int l, int r){return query(r) - query(l - 1);}
	void clear(){memset(t, 0, sizeof(t));}
}T;
int main(){
	freopen("light.in","r",stdin);
	freopen("light.out","w",stdout);
	n = read(), m = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= m; ++i){
		int l = read(), r = read();
		ans[i] = 1ll * (r - l + 1) * (a[r] - a[l]);
		if(r != l){
			ql[l].push_back(pii(r, i));
			qr[r].push_back(pii(l, i));
		}
	}
	st[0][1] = INT_MAX;
	for(int i = 2; i <= n; ++i)st[0][i] = a[i] - a[i - 1];
	for(int i = 1; (1 << i) <= n; ++i)
		for(int j = 1; j + (1 << i) - 1 <= n; ++j)
			st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
	for(int i = 1; i <= n; ++i){
		int l = i, r = i, p = i;
		ll sum = 0;
		while(l != 1 && r != n){
			int pre = a[p] - a[l - 1], nxt = a[r + 1] - a[p];
			if(pre < nxt){
				int np = queryl(l, nxt);
				pl[l - 1].push_back(pil(r, sum + a[p]));
				pl[np - 1].push_back(pil(-r, sum + a[p]));
				sum += a[p] - a[np];
				l = p = np;
			}else{
				int np = queryr(r + 1, pre) - 1;
				pr[r + 1].push_back(pil(l, sum - a[p]));
				pr[np + 1].push_back(pil(-l, sum - a[p]));
				sum += a[np] - a[p];
				r = p = np;
			}
		}
	}
	for(int i = 1; i <= n; ++i){
		for(auto it : pr[i]){
			if(it.first > 0)T.add(it.first, pli(it.second, 1));
			else T.add(-it.first, pli(-it.second, -1));
		}
		for(auto it : qr[i]){
			pli res = T.query(it.first + 1, n);
			ans[it.second] += res.first + 1ll * res.second * a[i];
		}
	}
	T.clear();
	for(int i = n; i >= 1; --i){
		for(auto it : pl[i])
			if(it.first > 0)T.add(it.first, pli(it.second, 1));
			else T.add(-it.first, pli(-it.second, -1));
		for(auto it : ql[i]){
			pli res = T.query(1, it.first - 1);
			ans[it.second] += res.first - 1ll * res.second * a[i];
		}
	}
	for(int i = 1; i <= m; ++i)printf("%lld\n",ans[i]);
	return 0;
}

C. 树状数组

\(f_{i, j, k}\) 表示考虑了前 \(i\) 个位置,当前与 \(r\) 的不同的二进制位最高为 \(j\), \(j\) 及以下有 \(k\) 个 \(1\) 的方案数。

倒着推一个转移系数 \(g_{i, j, k}\)。

对于询问把前后缀拼起来。

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 1e5 + 55, mod = 998244353;
int n, k, lim, id[25][25], tot, tr[25 * 25][2], f[maxn][25 * 25], g[maxn][25 * 25];
char s[maxn];
void add(int &x, int y){x += y; if(x >= mod)x -= mod;}
int lowbit(int x){return x & -x;}
int tr0(int x){return x - lowbit(x);}
int tr1(int x){return x + lowbit(((1 << k) - 1) ^ x);}
int find(int x){
	for(int i = k - 1; i >= 0; --i)if(((x ^ lim) >> i) & 1)return id[i][__builtin_popcount(x & ((1 << i) - 1))];
	return 0;
}
int main(){
	freopen("fenwick.in","r",stdin);
	freopen("fenwick.out","w",stdout);
	n = read(), k = read(); lim = read(); scanf("%s",s + 1);
	for(int i = 0; i < k; ++i)
		for(int j = 0; j <= i; ++j)id[i][j] = ++tot;
	for(int i = 0; i < k; ++i)
		for(int j = 0; j <= i; ++j){
			tr[id[i][j]][0] = j ? id[i][j - 1] : find(tr0(((lim >> i) ^ 1) << i));
			tr[id[i][j]][1] = j == i ? find(tr1((((lim >> i) ^ 1) << i) | ((1 << i) - 1))) : id[i][j + 1];
		}
	tr[find(lim)][0] = find(tr0(lim));
	tr[find(lim)][1] = find(tr1(lim));
	f[0][find(0)] = 1;
	for(int i = 1; i <= n; ++i)
		for(int j = 0; j <= tot; ++j){
			if(s[i] != '1')add(f[i][tr[j][0]], f[i - 1][j]);
			if(s[i] != '0')add(f[i][tr[j][1]], f[i - 1][j]);
		}
	for(int i = 0; i <= lim; ++i)g[n + 1][find(i)] = 1;
	for(int i = n; i >= 1; --i)
		for(int j = 0; j <= tot; ++j){
			if(s[i] != '1')add(g[i][j], g[i + 1][tr[j][0]]);
			if(s[i] != '0')add(g[i][j], g[i + 1][tr[j][1]]);
		}
	for(int i = 1; i <= n; ++i)
		if(s[i] == '1')printf("0\n");
		else{
			int ans = 0;
			for(int s = 0; s <= tot; ++s)add(ans, 1ll * f[i - 1][s] * g[i + 1][tr[s][0]] % mod);
			printf("%d\n",ans);
		}
	return 0;
}

标签:typedef,20,int,long,maxn,国赛,2023,return,first
From: https://www.cnblogs.com/Chencgy/p/17488770.html

相关文章

  • 【题解】[NOIP2017 提高组] 逛公园
    题目描述:策策同学特别喜欢逛公园。公园可以看成一张\(N\)个点\(M\)条边构成的有向图,且没有自环和重边。其中\(1\)号点是公园的入口,\(N\)号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。策策每天都会去逛公园,他总是从\(1\)号点进去,从\(N\)号......
  • 2023安洵杯—3D_maze
    3D_maze迷宫问题关键找迷宫结合移动以及最终的提示输出判断v5为左右移动,v4为上下移动,v3为跳到其他层,这是一个三维的迷宫,并且是一个此时能够得知是10×10×n,n还不清楚,不过代码中v3出现的最大值为5,此时推测n为6,也就是有6层,双击unk这个数组将数据提取出来发现有2400个,此时想到......
  • 数据结构课程设计2023夏7-4 先序和中序构造二叉树
    本题目要求用先序序列和中序序列构造一棵二叉树(树中结点个数不超过10个),并输出其后序序列。输入格式:在第一行中输入元素个数。第二行中输入先序序列,用空格分隔。第三行中输入中序序列,用空格分隔。输出格式:输出此二叉树的后序序列,用空格分隔,最后也有一个空格。输入样例:......
  • 2023冲刺国赛模拟 20.1
    我是越来越摆了,一下午就改了一道题;而且这么菜,看了半天的题解做法还没看懂。又是被暴踩的一天。T1树染色比较套路的想法是考虑当前以\(u\)为根的子树,考虑第一次选择\(u\)子树内的叶节点,此时我们必须选择\(u\)以上的节点作为链顶,这会对方案数产生贡献。考虑通过第一条链划......
  • 《近期回忆录》2023.6.17
    我们都是行走在镜面边缘的人。低下头看到的,是半个迷茫的自己,和半个不见底的深渊。——百度贴吧noip,《行走在镜面的边缘》记2023.5.5-2023.6.17,谨以此送给一个半月以来疯狂的自己。 日志阶段性sum瞎扯(bushi)  2023.5.7新的开始NOCAI创新编程初赛&&蓝桥......
  • 2023-06-17 tp6如何开启debug调试
    我安装的tp6没有.env文件,官网的文档是说把tp6在根目录生成的.exmaple.env文件改名为.env就可以了,如果没有该文件就直接创建一个,然后在里面添加代码:APP_DEBUG=true;如果想关闭调试则设置为false即可。注意:官方说明该调试只可用于本地测试,部署到生产环境时会失效。tp6官方文档:ht......
  • 3.2 鱼与熊掌可以兼得的深度学习-2022
    1.问题回顾  在上节的再谈宝可梦、数码宝贝分类问题上,我们提出了机器学习的分类原理.并提出了一个矛盾点:当可选参数过多,loss会变小,但理想和现实差距会很大;当可选参数比较少,loss会变大,但理想和现实差距会减小.现在我们需要一个Loss小,可选参数也少的模型.2.Whywene......
  • 面经2023
    东方甄选:Kafka和mq区别Varchar建立索引后用int查是否能使用索引Redis集群模式和非集群模式client有什么区别Redis集群模式怎么知道key在哪个槽是server端做的逻辑还是client做的分槽逻辑白龙马setnx和设置过期时间是原子操作不联合索引,如果用Abetween和B等于xx,是否会用到索......
  • 2023-06-17 闲话
    生活在这一周里面陷入了一团糟,不妨称之为随机生活。像吃饭睡觉这样的最最基础的物质生活完全没法保证规律,作息是随机作息:第一天到家的作息是三点到六点,中午睡了一小时,晚上熬夜看了欧冠决赛;前天是十二点到六点,昨天是十点到五点。你觉得这不是迈上正轨了吗,我觉得不然,比如我们看看......
  • P2161 [SHOI2009]会场预约 题解
    蒟蒻提供一种fhq-treap的做法,但是不如其他题解的快(也没有stl快,不开O21.8s),但是比较好想,扩展了fhq的模板,也算是为使用fhq提供一个新方法。首先,fhq-treap是什么,如果有同学不清楚,请点击学习(并非我的blog)那么,由于fhq树的分裂操作,使得我们可以很方便的取出我们想要的区间。那么,在......