Educational Codeforces Round 176 (CF2075)

A. To Zero

先减 \(k\),变成偶数,然后不停减 \(k-1\)

#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
int t; 
int n,k;
void solve(){
	scanf("%d%d",&n,&k);
	n-=k;
	printf("%d\n",(n+k-2)/(k-1)+1);
}
int main(){
	scanf("%d",&t);
	while(t--)solve();
    return 0;
}

B. Array Recoloring

显然,最后取到最大的 \(k+1\) 个数最优。

设选了 \(p_1 , p_2 \dots p_k\) ,那么可以控制最后一个选 \(a_1,a_2\)\(p_1\)\(p_k\)中的任何一个。

那么对于 \(k \geq 2\) 时,只要取到最大 \(k+1\) 个数中,最左边和最右边的数即可。

对于 \(k = 1\) 时,要么 \(a_1+a_n\) ,要么 \(\max(a_1,a_n)+\max(a_2,\dots,a_{n-1})\)

#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
int t; 
int n,k,a[5005];
void solve(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	if(k==1){
		int res=a[1]+a[n];
		int mx=0;for(int i=2;i<n;i++)mx=max(mx,a[i]);
		res=max(res,mx+max(a[1],a[n]));
		printf("%d\n",res);
		return ;
	}
	sort(a+1,a+1+n);
	ll res=0;
	for(int i=n-k;i<=n;i++)res+=a[i];
	printf("%lld\n",res);
}
int main(){
	scanf("%d",&t);
	while(t--)solve();
    return 0;
}

C. Two Colors

对于两个颜色,分别有 \(a,b\) 个,其中 \(a\leq b\)\(a+b\geq n\)

那么有 \(\min(b,n-1)-\max(n-a,1)+1\) 个方案。

拆个贡献就做完了。

(代码里把 \(+1\) 放到 \(a\) 的贡献里面了。)

#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
int t; 
int n,m,a[200005];
void solve(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d",&a[i]);
	sort(a+1,a+1+m);
	ll res=0;
	for(int i=1;i<=m;i++){
		int l=i+1,r=m,pos2=0,pos1=0;
		while(l<=r){
			int mid=(l+r>>1);
			if(a[mid]+a[i]>=n)pos2=mid,r=mid-1;
			else l=mid+1;
		}
		if(pos2)res-=(ll)(m-pos2+1)*max(n-a[i]-1,0);
		l=1,r=i-1;
		while(l<=r){
			int mid=(l+r>>1);
			if(a[mid]+a[i]>=n)pos1=mid,r=mid-1;
			else l=mid+1;
		}
		if(pos1)res+=(ll)(i-pos1)*min(a[i],n-1);
//		printf("%d %d %d\n",i,pos1,pos2);
	}
	printf("%lld\n",res*2);
}
int main(){
	scanf("%d",&t);
	while(t--)solve();
    return 0;
}

D. Equalization

最后剩下来的一定是 \(x\)\(y\) 的一个公共前缀,或者删完。

考虑预处理 \(f_{i,j}\) 表示一个要删 \(i\) 个,一个要删 \(j\) 个,最少的代价。

这个可以用一个01背包来维护,然后就做完了。

注意,\(f_{i,j}\) 没有单调性,比如 \(f_{10,4}\gt f_{10,5}\),所以枚举删完的情况要枚举完整。

#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
int t;
ll x,y,f[75][75];
void init(){
	memset(f,0x3f,sizeof(f));
	f[0][0]=0;
	for(int k=1;k<=60;k++)
		for(int i=70;i>=0;i--)
			for(int j=70;j>=0;j--){
				if(i>=k)f[i][j]=min(f[i][j],f[i-k][j]+(1LL<<k));
				if(j>=k)f[i][j]=min(f[i][j],f[i][j-k]+(1LL<<k));
			}
}
int ax[75],cntx,ay[75],cnty;
void solve(){
	for(int i=1;i<=cntx || i<=cnty;i++)ax[i]=ay[i]=0;
	cntx=cnty=0;
	scanf("%lld%lld",&x,&y);
	while(x)ax[++cntx]=x&1,x>>=1;
	while(y)ay[++cnty]=y&1,y>>=1;
	reverse(ax+1,ax+1+cntx);
	reverse(ay+1,ay+1+cnty);
	ll res=3e18;
	for(int i=1;i<=cntx && i<=cnty;i++){
		if(ax[i]!=ay[i])break;
		res=min(res,f[cntx-i][cnty-i]);
	}
	for(int i=cntx;i<=70;i++)
		for(int j=cnty;j<=70;j++)
			res=min(res,f[i][j]);
	printf("%lld\n",res);
}
int main(){
	scanf("%d",&t);
	init();
	while(t--)solve();
    return 0;
}

E. XOR Matrix

显然,\(a,b\) 中不能出现至少3个不同的数。

如果都只有一个不同的数,方案数为 \((A+1)(B+1)\)

如果有一个有一个不同的数。(设它是 \(a\)\(b\) 的情况是类似的)

那么方案数为 \((A+1)(^{B+1}_{\ \ \ 2})(2^m-2)\)

对于两个都选两个不同数的情况,设选的数为 \(a,b,c,d\) ,其中 \(a\neq b,c\neq d\)

得到的异或和为 \(a \bigoplus c,a\bigoplus d,b \bigoplus c,b \bigoplus d\)

其中必须有两对是相等的。

那么只能是 \(a \bigoplus c = b \bigoplus d\)

也就是4个数的异或和为0。

于是可以用数位dp来做,令 \(f_{i,j}\) 表示枚举到第 \(i\) 位,\(j\) 表示4个数是否顶着上限。(压了个位)

顶着上限的意思是,到枚举到的 \(i\) 为止,它的每一位都和上限一样。

转移是容易的。

#include<bits/stdc++.h>
using namespace std;
#define i128 __int128
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-x))
#define It set<int>::iterator
//#define ls (rt<<1)
//#define rs (rt<<1|1)
//#define mid (l+r>>1)
//#define lson tr[rt].ls
//#define rson tr[rt].rs
//#define ls1 tr[rt1].ls
//#define rs1 tr[rt1].rs
//#define ls2 tr[rt2].ls
//#define rs2 tr[rt2].rs
#define pb emplace_back
const int mod=998244353;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
bool check(int x){
	int sum=(x&1)+((x>>1)&1)+((x>>2)&1)+((x>>3)&1);
	return (sum&1);
}
int t;
int n,m,A,B;
bool check0(int p,int q,int r){
	int q0=q&1,q1=(q>>1)&1,q2=(q>>2)&1,q3=(q>>3)&1;
	int r0=r&1,r1=(r>>1)&1,r2=(r>>2)&1,r3=(r>>3)&1;
	int t0=(A>>p)&1,t1=(B>>p)&1;
	if(!t0 && q0 && r0)return 1;
	if(!t0 && q1 && r1)return 1;
	if(!t1 && q2 && r2)return 1;
	if(!t1 && q3 && r3)return 1;
	return 0;
}
int get(int p,int q,int r){
	int q0=q&1,q1=(q>>1)&1,q2=(q>>2)&1,q3=(q>>3)&1;
	int r0=r&1,r1=(r>>1)&1,r2=(r>>2)&1,r3=(r>>3)&1;
	int t0=(A>>p)&1,t1=(B>>p)&1,res=0;
	if(q0 && t0==r0)res|=1;
	if(q1 && t0==r1)res|=2;
	if(q2 && t1==r2)res|=4;
	if(q3 && t1==r3)res|=8;
	return res;
}
int work1(){
	int res=0;
	res=(res+(ll)(B+1)*B/2%mod*(A+1)%mod*(ksm(2,m)-2)%mod)%mod;
	res=(res+(ll)(A+1)*A/2%mod*(B+1)%mod*(ksm(2,n)-2)%mod)%mod;
	res=(res+(ll)(A+1)*(B+1))%mod;
	return res;
}
int f[35][19];
int work2(){
	memset(f,0,sizeof(f)); 
	f[30][15]=1;
	for(int i=29;i>=0;i--)
		for(int j=0;j<=15;j++)
			for(int k=0;k<=15;k++)if(!check(k)){
				if(check0(i,j,k))continue;
				int uj=get(i,j,k);
//				printf("%d %d %d %d\n",i,j,k,uj);
				f[i][uj]=(f[i][uj]+f[i+1][j])%mod;
			}
	int res=0;
	for(int i=0;i<=15;i++)res=(res+f[0][i])%mod;
	res=(res-(ll)(A+1)*(B+1)%mod+mod)%mod;
	res=(ll)res*(ksm(2,n)-2)%mod*(ksm(2,m)-2)%mod*ksm(4,mod-2)%mod;
	return res;
}
void solve(){
	scanf("%d%d%d%d",&n,&m,&A,&B);
	int res=work1()+work2();res%=mod;
	printf("%d\n",res);
}
int main(){
	scanf("%d",&t);
	while(t--)solve();
    return 0;
}
posted @ 2025-03-18 00:52  Kent530  阅读(170)  评论(0)    收藏  举报