首页 > 其他分享 >2023/2/21模拟赛

2023/2/21模拟赛

时间:2023-02-21 17:11:23浏览次数:25  
标签:tmp 21 int tot MAXN bitset 2023 模拟 MOD

呃呃,补不动了
开题顺序:T3->T1->T2
\(T1:\)
image

考场上想了个 \(n^2\) 的 \(DP\),只有六十……想了快一个小时。得知正解就是卡特兰数时追悔莫及。(参见卡特兰数)样例输入为 \(5\) \(3\),根据样例,把每种情况的 \(x_i\) 的指数写出来。

image

对于每个 \((a,b,c,d,e)\),\(a\) 表示的就是该方案下 \(x_1\) 的指数,以此类推。
再求一个前缀和:
image

不妨求前缀和后每个五元组看作五个坐标,纵坐标为 \(i\),横坐标就为求得的五元组中的 \(a_i\)。显然,这五个点连起来后的路径的终点是 \((5,3)\)。要求路径上的所有点都不在 \(y = x + 3\) 上。显然,最终的答案就是从 \((0,0)\) 到 \((n - k + 1,n)\) 的路径总数。考虑用卡特兰数来解决。
答案即为 \(2n - k + 1 \choose n - k + 1\) - \(2n - k + 1 \choose n - k\)。

所以实在不会做的时候还是得想想这些数学方面的知识?

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 3e5;
const int MOD = 998244353;
int ifac[MAXN + 5],n,k,fac[MAXN + 5];
int qpow(int a,int n){
	int ret = 1;
	while(n){
		if(n & 1)ret = ret * a % MOD;
		a = a * a % MOD;
		n /= 2;
	}
	return ret;
}
int c(int n,int m){
	return fac[n] * ifac[n - m] % MOD * ifac[m] % MOD;
}
signed main(){
	freopen("expand.in","r",stdin);
	freopen("expand.out","w",stdout);
	scanf("%d%d",&n,&k);
	fac[0] = 1;
	for(int i = 1; i <= 2 * n; i++){
		fac[i] = fac[i - 1] * i % MOD;
	}
	ifac[2 * n] = qpow(fac[2 * n],MOD - 2);
	for(int i = 2 * n; i >= 1; i--){
		ifac[i - 1] = ifac[i] * i % MOD;
	}
	int ans = ((c(n + n - k + 1,n - k + 1) - c(n + n - k + 1,n - k)) % MOD + MOD) % MOD;
	cout << ans;
}

\(T2:\)
image

还是不会,只会用 \(bitset\) 模拟下,\(bitset\) 的加法操作的函数还是要背背。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 1e5;
bitset<MAXN> tmp,one;
bitset<MAXN> add(bitset<MAXN> a,bitset<MAXN> b){
	return (b.any() ? add((a ^ b),((a & b) << 1)) : a);
}
signed main(){
	freopen("conj.in","r",stdin);
	freopen("conj.out","w",stdout);	
	cin >> tmp;
	one[0] = 1;
	int ans = 0;
	while(tmp.count() != 1 || tmp[0] != 1){
		ans++;
		if(tmp[0] == 1){
			tmp = add(tmp,tmp << 1);
			tmp = add(tmp,one);
		}
		else tmp >>= 1;
	}
	cout << ans;
}

放个题解先——
image

\(T3:\)
image

只会 \(60pts\) 的方法,可是考场上只用纯纯暴力写了 \(20pts\),剪枝的方法还是得多学习下。

至于这个题,就是把相关联的量放到一个连通块里进行考虑,每个连通块 \(dfs\) 下,大大降低时间复杂度。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 1e3;
int cnt,gett,n,m1,m2,tot,head[MAXN + 5],fo[MAXN + 5][MAXN + 5],mu[MAXN + 5][MAXN + 5],ans;
bool vis[MAXN + 5];
vector<int> vv,src[MAXN + 5];
struct EDGE{
	int u,v,next;
}edge[MAXN + 5];
void add(int u,int v){
	++tot;
	edge[tot].u = u;
	edge[tot].v = v;
	edge[tot].next = head[u];
	head[u] = tot;
}
void dfs1(int u,int now){
	src[now].push_back(u);
	for(int i = head[u]; i; i = edge[i].next){
		int v = edge[i].v;
		if(!vis[v]){
			vis[v] = 1;
			dfs1(v,now);
		}
	}
}
void dfs(int cntt,int now){
	if(cntt == src[now].size()){
		for(int i = 0; i < vv.size(); i++){
			int v = vv[i];
			for(int j = 1; j <= mu[v][0]; j++){
				if(!vis[mu[v][j]])return;
			}
			
			for(int j = 1; j <= fo[v][0]; j++){
				if(vis[fo[v][j]])return;
			}
		}
		++gett;
		return;
	}
	vis[src[now][cntt]] = 1;
	vv.push_back(src[now][cntt]);
	dfs(cntt + 1,now);
	vv.pop_back();
	vis[src[now][cntt]] = 0;
	dfs(cntt + 1,now);
}
signed main(){
	freopen("treasure.in","r",stdin);
	freopen("treasure.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m1,&m2);
	for(int i = 1; i <= m1; i++){
		int u,v;
		scanf("%lld%lld",&u,&v);
		mu[u][++mu[u][0]] = v;
		add(u,v);
		add(v,u);
	}
	for(int i = 1; i <= m2; i++){
		int u,v;
		scanf("%lld%lld",&u,&v);
		fo[u][++fo[u][0]] = v;
		fo[v][++fo[v][0]] = u;
		add(u,v);
		add(v,u);
	}
	for(int i = 1; i <= n; i++){
		if(!vis[i]){
			vis[i] = 1;
			dfs1(i,++cnt);
		}
	}
	int ans = 1;
	memset(vis,0,sizeof vis);
	for(int i = 1; i <= cnt; i++){
		gett = 0;
		dfs(0,i);
		ans *= gett;
	}
	cout << ans;
}
//5 3 3
//1 2
//1 4
//2 5
//3 5
//4 5
//3 5

题解:
image
image

\(T4:[WC]远古计算机\)
还不太会……再做做。。。

标签:tmp,21,int,tot,MAXN,bitset,2023,模拟,MOD
From: https://www.cnblogs.com/CZ-9/p/17141580.html

相关文章