首页 > 其他分享 >CF 1749 题解

CF 1749 题解

时间:2022-11-04 09:57:23浏览次数:85  
标签:lc int 题解 CF long maxn 1749 include define

比赛链接:https://codeforces.com/contest/1749

题解:
AB
水题

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

int r[15],c[15];

void solve(){
	int n,m;scanf("%d%d",&n,&m);
	memset(r,0,sizeof r);memset(c,0,sizeof c);
	for(int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		r[x] = c[y] = 1;
	}
	int fg = 0;
	for(int i=1;i<=n;i++)
		fg |= r[i] == 0,
		fg |= c[i] == 0;
	if(fg)puts("YES");
	else puts("NO");
}

signed main(){
	int te;scanf("%d",&te);
	while(te--)solve();

	return 0;
}
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

signed main(){
	int te;scanf("%d",&te);
	while(te--){
		int n;scanf("%d",&n);
		LL sum=0,mx=-1e18;;
		for(int i=1,x;i<=n;i++)scanf("%d",&x),sum+=x;
		for(int i=1,x;i<=n;i++)scanf("%d",&x),sum+=x,mx=max(mx,1ll*x);
		printf("%I64d\n",sum-mx);
	}

	return 0;
}

C
Bob肯定优先取小的,Alice优先取大的。枚举k暴力模拟这个过程即可

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

void solve(){
	int n;scanf("%d",&n);
	int a[105];
	int bin[105],ain[105];memset(bin,0,sizeof bin);memset(ain,0,sizeof ain);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),++bin[a[i]],++ain[a[i]];
	for(int i=2;i<=100;i++)ain[i]+=ain[i-1];
	int bbin[105],aain[105];
	memcpy(bbin,bin,sizeof bbin);memcpy(aain,ain,sizeof aain);
	int qz = 0;
	for(int k=100;k>=1;k--){
		memcpy(bin,bbin,sizeof bin);memcpy(ain,aain,sizeof ain);
		int gg=0;qz=0;
		for(int i=k;i>=1;i--){
			if(ain[i] - qz <= 0){
				gg=1;break;
			}
			if(bin[i] == 0)
				for(int j=i;j>=1;j--)
					if(bin[j]){--bin[j];--ain[j];break;}
					else -- ain[j];
			++ qz;
		}
		if(!gg){printf("%d\n",k);return ;}
	}
	puts("0");
}

signed main(){
	int te;scanf("%d",&te);
	while(te --)solve();

	return 0;
}

D
[1..1]显然是一组解,考虑能不能有其它解
考虑容斥,什么情况下无解?对于所有的a[i],所有的\(1\leq j \leq i\),都有\(gcd(a[i],j) \neq 1\)
显然只需要考虑素因子即可,也即是1~i的所有素数即可
从1~n,如果当前i为素数,那么\(cds = cds \times i\),当前这一位出现不合法序列的次数是i/cds,然后 tmp = tmp * i/cds,tmp表示的就是长度为 i 的所有不合法序列的个数,对于所有的i计算一下即可
总共的情况是什么呢?因为每一位可以任意取,就是m+m*m+...+pw(m,n)
容斥一下即可
需要快速乘

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 3e5 + 5, mod=998244353;

int notpm[maxn], pm[maxn], pcnt=0;

void xxs(){
	notpm[1] = 1;
	for(int i=2;i<=300000;i++){
		if(!notpm[i]){
			pm[++ pcnt] = i;
		}
		for(int j=1;j<=pcnt && i * pm[j] <= 300000; j++){
			notpm[i*pm[j]] = 1;
			if(i%pm[j] == 0)break;
		}
	}
}

int n;
LL m;
LL bs = 1, nbs = 1;
int gg = 0;
int tmp =1 ;
inline LL ksc(LL x,LL y,LL p){
	LL z=(long double)x/p*y;
	LL res=(ULL)x*y-(ULL)z*p;
	return (res+p)%p;
}
signed main(){
	scanf("%d%I64d",&n,&m);
	xxs();
	int pi = 1;
	LL ans = 0;
	for(int i=1;i<=n;i++){
		bs = ksc(bs, m, mod);
//		bs = 1ll * bs * m % mod;
		if(pm[pi] == i && !gg){
			nbs = 1ll * nbs * pm[pi];
			if(nbs > m){
				gg = 1;
			}
			++ pi;
		}
		(ans += bs) %= mod;
		if(!gg){
			tmp = ksc(tmp, m/nbs, mod);
//			tmp = 1ll * tmp * (m/nbs) % mod;
			(ans += mod - tmp) %= mod;
		}
//		cout << nbs << " "<< bs << " " << gg << '\n';
	}
	printf("%I64d\n",ans);

	return 0;
}

E
我的01bfs博客中有这个题

F
考虑简化版:对每个点子树中距离这个点为d(0~20)的所有点进行修改,查找点权?
显然直接对这个点修改,查询的时候对于所有的0~20的树,求ans0[fa[x]] + ans1[fa[fa[x]]] + ... 即可
回到这个题,(u,v)路径,设lca为lc
可以拆成这3个路径:[u,lc) (lc,v] lc及fa[lc],...
[u,lc):按照简化版的处理,对于ansd[u]+k, ansd[fa[u]]+k, ... ansd[son[lc]]+k,表示对于u的子树中距离u为d的点权都+k,...
注意这里会存在son[lc]子树中距离son[lc]距离<d的点没有处理,但是这块能被包含在lc fa[lc] ... 中,此处不在赘述
[v,lc):同理
lc fa[lc] .. : 手玩一下发现ansd[lc]+k ans(d-1)[lc]+k ans(d-1)[fa[lc]]+k ans(d-2)[fa[lc]]+k ... 可以涵盖所有情况。注意如果到根了,需要把d d-1 d-2.. 0都给加上
因此我们需要实现的是:树上链加、单点加、单点查询
树剖解决,也可以树状数组
时间复杂度O(qdlogn)

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 2e5+5;

int n;
vector<int>g[maxn];
int a[maxn];
int dfn[maxn], seq[maxn], dfs_clock;
int dep[maxn], heavy[maxn], top[maxn], sz[maxn], fa[maxn];
struct seg{
	int sum,lazy;
}se[maxn << 2][23];

void dfs1(int x,int fat){
	fa[x] = fat;
	sz[x] = 1;
	dep[x] = dep[fat] + 1;
	
	for(int u : g[x]){
		if(u == fat)continue;
		dfs1(u, x);
		sz[x] += sz[u];
		if(!heavy[x] || sz[u] > sz[heavy[x]])
			heavy[x] = u;
	}
}

void dfs2(int x,int now){
	top[x] = now;
	dfn[x] = ++ dfs_clock;
	seq[dfs_clock] = x;
	
	if(!heavy[x])return ;
	dfs2(heavy[x], now);
	for(int u : g[x]){
		if(u == heavy[x] || u == fa[x])continue;
		dfs2(u,u);
	}
}

void build(int x,int y,int num){
	for(int i=0;i<=20;i++)se[num][i].sum = se[num][i].lazy = 0;
	if(x == y){
		return ;
	}
	int mid = x + y >> 1;
	build(x,mid,num << 1);build(mid+1, y, num<<1 | 1);
}

void pushdown(int l,int r,int num,int d){
	if(!se[num][d].lazy)return ;
	int mid = l+r>>1;
	(se[num << 1][d].sum += 1ll*(mid-l+1)*se[num][d].lazy);
	(se[num << 1|1][d].sum += 1ll * (r-mid)*se[num][d].lazy);
	se[num << 1][d].lazy += se[num][d].lazy;
	se[num << 1|1][d].lazy += se[num][d].lazy; 
	se[num][d].lazy = 0;
}

int getlca(int x,int y){
	int tx = top[x], ty = top[y];
	while(tx != ty){
		if(dep[tx] < dep[ty])swap(x, y), swap(tx, ty);
		x = fa[tx], tx = top[x];
	}
	if(dep[x] > dep[y])return y;
	return x;
}

void update(int x,int y,int k,int l,int r,int num,int d){
	if(x <= l && r <= y){
		(se[num][d].sum += 1ll * (r-l+1) * k);
		se[num][d].lazy += k;
		return ;
	}
	pushdown(l,r,num,d);
	int mid = l+r >> 1;
	if(y <= mid)update(x,y,k,l,mid,num<<1,d);
	else if(x > mid)update(x,y,k,mid+1,r,num<<1|1,d);
	else update(x,y,k,l,mid,num<<1,d), update(x,y,k,mid+1,r,num<<1|1,d);
	se[num][d].sum = (se[num<<1][d].sum + se[num<<1|1][d].sum);
}

void upd(int to,int k,int l,int r,int num,int d){
	if(l == r){
		se[num][d].sum += k;
		return ;
	}
	pushdown(l,r,num,d);
	int mid = l+r>>1;
	if(to<=mid)upd(to,k,l,mid,num<<1,d);
	else upd(to,k,mid+1,r,num<<1|1,d);
	se[num][d].sum = se[num << 1][d].sum + se[num<<1|1][d].sum; 
}

void access(int x,int k,int d){
	int curd = d;
	while(1){
		upd(dfn[x],k,1,n,1,curd);
		if(curd == 0)break;
		upd(dfn[x],k,1,n,1,--curd);
		
		if(x == 1)break;
		x = fa[x];
	}
	while(curd >= 1)upd(dfn[1],k,1,n,1,--curd);
}

int query(int to,int l,int r,int num,int d){
	if(l == r)return se[num][d].sum;
	int mid = l+r>>1;
	pushdown(l,r,num,d);
	if(to <= mid)return query(to,l,mid,num<<1,d);
	else return query(to,mid+1,r,num<<1|1,d);
}

void chain_add(int x,int y,int k,int d){
//	printf("(%d,%d)\n",x,y);
	int tx = top[x], ty = top[y];
	while(tx != ty){
		if(dep[tx] < dep[ty])swap(x, y), swap(tx, ty);
		update(dfn[tx], dfn[x], k, 1, n ,1, d);
		x = fa[tx], tx = top[x]; 
	}
	if(dep[x] > dep[y])swap(x, y);
	update(dfn[x], dfn[y], k, 1, n, 1, d);
}

signed main(){
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++){
		int x,y;scanf("%d%d",&x,&y);
		g[x].push_back(y), g[y].push_back(x);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,n,1);
	
	int m;scanf("%d",&m);
	while(m --){
		int op;scanf("%d",&op);
		if(op == 1){
			int x;scanf("%d",&x);
			int curx = x;
			int ans = 0;
			for(int d = 0;d<=20;d++){
				ans += query(dfn[curx],1,n,1,d);
				if(curx == 1)break;
				curx = fa[curx];
			}
			printf("%d\n",ans);
		}
		if(op == 2){
			int u,v,k,d;scanf("%d%d%d%d",&u,&v,&k,&d);
			int lc = getlca(u, v);
//			printf("?? %d\n",lc);
			if(lc == u || lc == v){
				int tx = lc == u ? v : u;
				int ty = lc;
				chain_add(tx,ty,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				access(lc, k, d); 
			}else{
				chain_add(u,lc,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				chain_add(v,lc,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				access(lc, k, d);
			}
		}
	}

	return 0;
}

标签:lc,int,题解,CF,long,maxn,1749,include,define
From: https://www.cnblogs.com/SkyRainWind/p/16856709.html

相关文章

  • P4774 倚天屠龙传 题解
    其实这道题的主体并不难,主要是细节很多我们可以把题目分成界限分明的两部分,第一部分,屠每条龙所用的剑只和当前拥有的剑有关。于是可以单独开一个数据结构按题目维护。另......
  • CF *2700泛做
    经典永流传CF961GPartitions观察\(W(S)=|S|\sum_{x\inS}w_x\),它可以看作是对于\(S\)的每个数都向集合内其他数(包括自己)贡献自己的\(w\)。每个数对自己的贡献是次......
  • 2022 CSP-S题解
    T1:假期计划给定\(n\)个点\(m\)条边的无向图,每个点有一个点权。在图中选\(4\)个不同的点,从\(1\)号点出发完成\(5\)段行程:\(1\toA\toB\toC\toD\to1\),每......
  • JOIOI の塔 题解
    题目传送门洛谷上竟然还没有题解...题目分析简单贪心题。考虑倒过来寻找。显然,如果一个J想要配成一座塔,那么必须要找一个OI。O更简单,就是直接找到一个I放上去就......
  • CF912D 小鱼仔 题解
    这是一个很邪门的贪心考虑到最终答案是每个正方形的贡献除以总的正方形个数,而正方形个数容易计算,那么只需最大化贡献。从题面给出的图易得每个点被覆盖的次数是一定的,我......
  • 等腰三角形ABC中,AB=AC,D是AC上一点,AE//BD,点F是AE上一点,CF交BD于点M,∠EBD=2∠ABC=2∠CMD
    2022年11月3日20点48分END......
  • NCF(NeuCharFramework)框架的使用 当前所用框架版本(0.3.1-beta3)
    1、官网介绍:NCF-NeuCharFramework|NCF文档2、下载NCF框架代码:https://github.com/NeuCharFramework/NCF3、运行NCF框架用vs2022打开下载的NCF项目NCF\src\back-en......
  • CF735E Ostap and Tree
    看到这题,有一个naive的DP做法,\(f[u][i][j]\)表示\(u\)节点的子树内近的黑点距离为\(i\),距离最远的非合法点距离为\(j\),然后转移一下,貌似是能过的。但我们可以再......
  • ckeditor粘贴word图片问题解决
    ​ 自动导入Word图片,或者粘贴Word内容时自动上传所有的图片,并且最终保留Word样式,这应该是Web编辑器里面最基本的一个需求功能了。一般情况下我们将Word内容粘贴到Web编辑......
  • [ARC087F] Squirrel Migration 题解
    [ARC087F]SquirrelMigration给你一个\(n\)个节点的树,求一个\(1\simn\)的排列\((p_1,p_2,\dotsp_n)\),使得\(\sumdist(i,p_i)\)最大。求这样的排列个数。答案......