【CodeForces】 Educational Codeforces Round 94

好久没来更新博客了,正好有空,总结一下 CF 1400 这场比赛。

ABCDE pp,B fst,rating+48

A. String Similarity

非常简单的构造题。(w) 的第 (i) 位填上 (s) 的第 (2i+1) 位即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1000009;

int n,m,a[N];
char c[50];

int main() {
	int T; scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		scanf("%s",c+1);
		for(int i=1;i<=n;i++) putchar(c[i+i-1]);
		putchar('
');
	}
	return 0;
}

B. RPG Protagonist

我 FST 的一道题目。原因是没开 long long /kk

感觉是 ABCD 中最难的一道题目。枚举带的剑的个数,然后贪心去做。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+9;

int n,m,p,f,cs,cw,s,w,ans;

int a[N],b[N];

signed main() {
	int T; scanf("%lld",&T);
	while(T--) {
		scanf("%lld%lld%lld%lld%lld%lld",&p,&f,&cs,&cw,&s,&w);
		if(w<s) swap(s,w), swap(cs,cw);
		ans=0;
		for(int i=0;i<=cs;i++) {
			int sum=0;
			int rest_s=cs-i, rest_w=cw;
			if(i*s>p) sum+=p/s;
			else {
				p-=i*s;
				if(p/w<=rest_w) rest_w-=p/w, sum+=p/w;
				else sum+=rest_w, rest_w=0;
				sum+=i, p+=i*s;
			}
			if(rest_s*s>f) sum+=f/s;
			else {
				f-=rest_s*s;
				if(f/w<=rest_w) rest_w-=f/w, sum+=f/w;
				else sum+=rest_w, rest_w=0;
				sum+=rest_s, f+=rest_s*s;
			}
			ans=max(ans,sum);
		}
		printf("%lld
",ans);
	}
	return 0;
}

C. Binary String Reconstruction

还是小清新构造题。先把那些 0 给安排好(可以确定两个位置),其他位置全部填上 1。判断一下是否可行即可。

比赛的时候 WA2 了 2 次,原因应该是判断是否可行的 if 里面出了问题。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;

int n,x,a[N];
char c[N],w[N];

int main() {
	int T; scanf("%d",&T);
	while(T--) {
		scanf("%s%d",c+1,&x);
		n=strlen(c+1);
		for(int i=1;i<=n;i++) w[i]='a';
		for(int i=1;i<=n;i++)
			if(c[i]=='0') w[max(i-x,0)]='0', w[min(i+x,n+1)]='0';
		bool flag=0;
		for(int i=1;i<=n;i++)
			if(c[i]=='1') {
				if((i-x<=0||w[i-x]=='0')&&(i+x>n||w[i+x]=='0'))
					flag=1;
			}
		if(flag) {puts("-1");continue;}
		for(int i=1;i<=n;i++) if(w[i]=='a') w[i]='1';
		for(int i=1;i<=n;i++) putchar(w[i]);
		puts("");
	}
	return 0;
}

D. Zigzags

数数题,但是不用用到任何的数据结构。可以用预计算解决。设

[f(i,j)=sum_{kle j} [a_i=a_k]\ g(i,j)=sum_{kge j} [a_i=a_k] ]

可以增量式统计。

[ans=sum_{k=3}^{n-1}sum_{j=2}^{k-1} f(k,j-1)g(j,k+1) ]

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3009;

int n,m,a[N],f[N][N],g[N][N],ans;

signed main() {
	int T; scanf("%lld",&T);
	while(T--) {
		scanf("%lld",&n);
		for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
		ans=0;
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) f[i][j]=f[i][j-1]+(a[i]==a[j]);
			for(int j=n;j>=1;j--) g[i][j]=g[i][j+1]+(a[i]==a[j]);
		}
		for(int k=3;k<n;k++)
			for(int j=2;j<k;j++)
				ans+=f[k][j-1]*g[j][k+1];
		printf("%lld
",ans);
	}
	return 0;
}

E. Clear the Multiset

重题啊……

贪心的考虑,对于一个区间,要么操作(最小的数)次操作一,要么操作 (r-l+1) 次操作二,递归处理。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5009;

int n,a[N];

int dp(int l,int r,int ret=0) {
	if(l>r) return 0;
	if(l==r) return min(1ll,a[l]);
	int min_a=0x3f3f3f3f3f3f3f3f;
	for(int i=l;i<=r;i++) min_a=min(min_a,a[i]);
	ret+=min_a;
	for(int i=l;i<=r;i++) a[i]-=min_a;
	int last_zero=l-1;
	for(int i=l;i<=r;i++) if(!a[i])
		ret+=dp(last_zero+1,i-1), last_zero=i;
	ret+=dp(last_zero+1,r);
	return min(ret,r-l+1);
}

signed main() {
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	printf("%lld",dp(1,n));
	return 0;
}

G. Mercenaries

先考虑没有互相讨厌的情况。我们枚举选多少个雇佣兵。设 (p_i) 表示可以接受有 (i) 个雇佣兵的人数,则 (ans=sumlimits_i binom{p_i}{i})

然后考虑有互相讨厌的情况。考虑大力容斥。枚举哪些冲突发生了(用状压枚举子集的方法),然后这里面的人都要被选中,设这些人的人数为 (k)。设这些一定要被选中的人的 ([l,r]) 的交集为 ([L,R]),则这部分对答案的贡献是

[sum_{i=L}^{R} dbinom {p_i-k}{i-k} ]

这个 (sum) 可以前缀和预计算。复杂度 (O(nm+m2^m))

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+9, M=29, mod=998244353;

int n,m,l[N],r[N],u[N],v[N];

int fac[N],inv[N],ifac[N];
void pre() {
	inv[0]=inv[1]=fac[0]=ifac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
	for(int i=2;i<=n;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
	for(int i=1;i<=n;i++) ifac[i]=ifac[i-1]*inv[i]%mod;
}
int C(int x,int y) {
	if(x<0||y<0||x<y) return 0;
	else return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}

int cf[N],p[N],s[N][49];
void cal_p() {
	for(int i=1;i<=n;i++) cf[l[i]]++, cf[r[i]+1]--;
	int ssum=0;
	for(int i=1;i<=n;i++) ssum+=cf[i], p[i]=ssum;
	for(int j=0;j<=2*m;j++) for(int i=1;i<=n;i++) {
		s[i][j]=(s[i-1][j]+C(p[i]-j,i-j))%mod;
	}
}

struct hset {
	bool vst[N];
	int ar[N], size;
	void clear() {
		for(int i=1;i<=size;i++) vst[ar[i]]=0;
		size=0;
	}
	void add(int x) {if(!vst[x]) ar[++size]=x, vst[x]=1;}
}st;

#define bit(S,i) (bool)((1<<i-1)&S)
int ans;
void in_ex() {
	for(int S=0;S<(1<<m);S++) {
		int L=1, R=n, pop=0;
		for(int j=1;j<=m;j++) if(bit(S,j)) {
			L=max(L,l[u[j]]), R=min(R,r[u[j]]), st.add(u[j]);
			L=max(L,l[v[j]]), R=min(R,r[v[j]]), st.add(v[j]);
			pop++;
		}
		if(L>R) {st.clear();continue;}
		int res=(s[R][st.size]-s[L-1][st.size]+mod)%mod;
		ans=(ans+res*(pop&1 ? -1 : 1)+mod)%mod;
		st.clear();
	}
}

signed main() {
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld%lld",&l[i],&r[i]);
	for(int i=1;i<=m;i++) scanf("%lld%lld",&u[i],&v[i]);
	pre();
	cal_p();
	in_ex();
	printf("%lld",(ans+mod)%mod);
	return 0;
}
原文地址:https://www.cnblogs.com/TetrisCandy/p/cf-1400.html