【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('\n');
	}
	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\n",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_{k\le j} [a_i=a_k]\\ g(i,j)=\sum_{k\ge 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\n",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=\sum\limits_i \tbinom{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;
}
posted @ 2020-09-01 14:54  LarsWerner  阅读(169)  评论(0编辑  收藏  举报