CF1739 部分题解

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

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;

signed main(){
	int te;scanf("%d",&te);
	while(te --){
		int n,m;scanf("%d%d",&n,&m);
		if(n == 1 || m == 1){
			puts("1 1");continue;
		}
		if(max(n, m) >= 4){
			puts("1 1");continue;
		}
		puts("2 2");
	}

	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;

void solve(){
	vector<int>vc;vc.clear();
	int n;scanf("%d",&n);
	int gg=0;
	for(int i=1;i<=n;i++){
		int x;scanf("%d",&x);
		if(i == 1)vc.push_back(x);
		else{
			int lst = vc[vc.size() - 1];
			if(x > 0 && lst - x >= 0){
				gg=1;
			}else vc.push_back(x + lst);
		}
	}
	if(gg){puts("-1");return ;}
	for(int i : vc)printf("%d ",i);puts("");
}

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

	return 0;
}

C
以 n=8为例,考虑draw的情况就是 2 3 6 7 || 1 4 5 8这种“螺旋”的,从大到小每次枚举当前剩下最大值在哪,每次加一个组合数即可,判一下最后一个1在哪

// 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, mod =998244353;

int fac[65], inv[65];

int pw(int x,int y){
	if(y == 0)return 1;
	if(y == 1)return x;
	int mid = pw(x, y>>1);
	if(y&1)return 1ll*mid*mid%mod*x%mod;
	return 1ll*mid*mid%mod;
}

int C(int x,int y){
	return 1ll * fac[x] * inv[x-y] % mod * inv[y]%mod;
}

void solve(){
	int n;scanf("%d",&n);
	int r1 = 0, r2 = 0;
	int cur = n -1 ;
	for(int i = n/2 -1,p=1; i>=1; i--,p++){
		if(i == n/2-1)r1 += C(cur,i), --cur;
		else{
			if(p&1)r1 += (C(cur, i)+C(cur-1,i))%mod;
			else r2 += (C(cur,i)+C(cur-1,i))%mod;
			cur -= 2;
		}
		r1 %= mod, r2 %= mod;
	}
	if(n%4 == 0)++ r2;
	else ++ r1;
	if(n%4 == 0)++ r2;
	else if(n>2)++ r1;
	printf("%d %d 1\n",r1,r2);
}

signed main(){
	fac[0] = inv[0] = 1;
	for(int i=1;i<=60;i++)fac[i] = 1ll*fac[i-1]*i%mod;
	inv[60] = pw(fac[60], mod -2 );
	for(int i=59;i>=1;i--)inv[i] = 1ll * inv[i+1]*(i+1)%mod;
	int te;scanf("%d",&te);
	while(te --)solve();

	return 0;
}

D
显然先二分答案
直接贪心会有反例,比如:
1 5 1 1 2 3 3
答案是2而非3,断2->3边
这启示我们可以自底向上贪心,每次遇到当前子树最大深度>=mid的话而且当前点不是根且父亲不是根,就把当前子树连到根

// 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,k;
vector<int>g[maxn];
int dep[maxn];
int tot = 0;

int dfs2(int x,int fat,int lim){
	int curd = 0;
	for(int u : g[x]){
		curd = max(curd, dfs2(u, x,lim ));
	}
	++ curd;
	if(fat != 1 && x != 1 && curd >= lim){++tot;return 0;}
	return curd;
}

int check(int x){
	tot = 0;
	dfs2(1,-1,x);
//	printf("?? %d\n",tot);
	if(tot > k)return 0;
	return 1;
}

void solve(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)g[i].clear();
	for(int i=2;i<=n;i++){
		int p;scanf("%d",&p);
		g[p].push_back(i);
	}
	int l=1,r=n, ans;
//	for(int i=1;i<=n;i++)printf("%d ",dep[i]);puts("");
//	printf("%d\n",check(1));
//	return ;
	while(l <= r){
		int mid = l +r >>1;
		if(check(mid))r = mid-1, ans =mid;
		else l = mid+1;
	}
	printf("%d\n",ans);
}

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

	return 0;
}

E
手玩一下全是1的样例发现,如果会出现二选一的情况,一定是(i,j)->(i,j+1)->(i+1,j+1)->(i+1,j+2)这种路径(其中(i,j+1)是1跳过了)
考虑dp,设\(dp[i][j]\)表示到(i,j)结尾的答案,其中是第一次到第j列
转移考虑普通的向右转移,还有一种如果(i^1,j)的数为1的话,那么(i,j+1)如果也为1,就是上面的螺旋走最优,如果为0,显然也是经过1更优
分析一下似乎情况就全了

// 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;
char s[2][maxn];
int dp[2][maxn][2];

void ck(int &mm,int a){mm = max(mm, a);}

signed main(){
	memset(dp, -0x3f, sizeof dp);
	scanf("%d",&n);
	for(int i=0;i<=1;i++)scanf("%s", s[i] + 1);
	s[0][n+1] = s[1][n+1] = '0';
//	dp[0][0][0] = 0;
//	printf("%d\n",dp[0][0][0]);
	dp[0][1][s[1][1] - '0'] = s[1][1] - '0';
	for(int i=1;i<=n;i++){
		for(int j=0;j<=1;j++){
			
		}
	}
//	printf("%d\n",dp[1][2][1]);
	printf("%d\n",max(dp[0][n+1][0], dp[1][n+1][0]));

	return 0;
}
posted @ 2022-10-05 20:33  SkyRainWind  阅读(12)  评论(0编辑  收藏  举报