CodeForces Round #841 (Div. 2) vp记

返回目录

在 2022 年的最后一天,和大神 stO Jerry__Jiang Orz 开了一场 CodeForces 的 vp,顺便来水一下博客

前言:前两题的输出为 actual answer ×2022

CodeForces Round #841 (Div. 2) vp记

Problem A

这道题没啥难度吧,由小学知识“积一定,差越大,和越大”可以推出,我们将其它数都变为 1,就是最优决策。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define repe(i,l,r) for(int (i)=l;(i)<=r;(i)++)
#define rep(i,n) for(int (i)=1;(i)<=n;(i)++)
#define FOR(i,r,l) for(int (i)=r;(i)>=l;(i)--)
#define INF 0x3f3f3f
#define pii pair<int,int>
#define mpr make_pair
#define pb push_back
#define ALL(v) (v).begin(),(v).end()
#define rsort(v) sort(ALL(v),greater<int>())
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
using namespace std;
int read(){int sum=0,f=1;char c;c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){sum=(sum<<1)+(sum<<3)+(c-'0');c=getchar();}return sum*f;}
void out(int x){if(x<0){x=-x;putchar('-');}if(x>=10)out(x/10);putchar(x%10+'0');}
template <typename T>void die(T s){cout<<s<<endl;exit(0);}
int fast(int a,int b,int P){int res=1;if(P<=0){while(b){if(b&1)res=res*a;a=a*a;b>>=1;}}else{while(b){if(b&1)res=res*a%P;a=a*a%P;b>>=1;}}return res;}
template <typename T>void chkmax(T& a,T b){if(a<b)a=b;return;}
template <typename T>void chkmin(T& a,T b){if(a>b)a=b;return;}
int T,a[55],n,res;
void solve(){
	res=1;n=read();
	rep(i,n)a[i]=read(),res=res*a[i];
	cout<<(res+n-1)*2022<<endl;
	return;
}
signed main(){
	T=read();
	while(T--)solve();
	return 0;
}

Problem B

这道题有一小点难度,具体结论我们可以感性证明一下:

我们可以假设现在我们在坐标 (i,j) ,并且从 (1,1)(i,j) 都采取了最优策略,我们思考下一步往哪边走更优

  • i<j ,不难看出,此时我们向下走是更优的
  • i>j ,此时向右走更优
  • 最后一种情况 i=j ,两者皆可

随后我们就可以想出 (1,1)(1,2)(2,2)(n,n) 是最优方案。

答案即为 i=1ni2+i=1n1i2+i=1n1i

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define repe(i,l,r) for(int (i)=l;(i)<=r;(i)++)
#define rep(i,n) for(int (i)=1;(i)<=n;(i)++)
#define FOR(i,r,l) for(int (i)=r;(i)>=l;(i)--)
#define INF 0x3f3f3f
#define pii pair<int,int>
#define mpr make_pair
#define pb push_back
#define ALL(v) (v).begin(),(v).end()
#define rsort(v) sort(ALL(v),greater<int>())
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
using namespace std;
int read(){int sum=0,f=1;char c;c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){sum=(sum<<1)+(sum<<3)+(c-'0');c=getchar();}return sum*f;}
void out(int x){if(x<0){x=-x;putchar('-');}if(x>=10)out(x/10);putchar(x%10+'0');}
template <typename T>void die(T s){cout<<s<<endl;exit(0);}
int fast(int a,int b,int P){int res=1;if(P<=0){while(b){if(b&1)res=res*a;a=a*a;b>>=1;}}else{while(b){if(b&1)res=res*a%P;a=a*a%P;b>>=1;}}return res;}
template <typename T>void chkmax(T& a,T b){if(a<b)a=b;return;}
template <typename T>void chkmin(T& a,T b){if(a>b)a=b;return;}
const int P=1e9+7;
int n,T;
int Sum(int x){
	return x*(x+1)%P*(2*x+1)%P*fast(6,P-2,P)%P;
}
void solve(){
	n=read();
	int ans=Sum(n)+Sum(n-1);
	ans=ans%P;
	ans=ans+(n-1)*n%P*fast(2,P-2,P)%P;
	ans=ans%P;
	cout<<ans*2022%P<<endl;
	return;
}
signed main(){
	T=read();
	while(T--)solve();
	return 0;
}

Problem C

这道题我在关上电脑后 10s 想出正解

为什么我在比赛没结束要关电脑

首先,由小学知识,我们可以发现,不符合要求的数仅可能是平方数,然后,我们可以发现做不下去了。

平方数在二进制中并没有什么性质,如果暴力去算的话时间复杂度为O((nn)×n),很明显会 TLE。

既然如此,我们就要想到————正难则反。

很明显,总答案数为 (n+1)×n2 ,我们可以枚举每个平方数,然后计算有哪些区间 xor 后得到这个数,很明显我们可以利用前缀异或优化。时间复杂度O(n×n)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define repe(i,l,r) for(int (i)=l;(i)<=r;(i)++)
#define rep(i,n) for(int (i)=1;(i)<=n;(i)++)
#define FOR(i,r,l) for(int (i)=r;(i)>=l;(i)--)
#define INF 0x3f3f3f
#define pii pair<int,int>
#define mpr make_pair
#define pb push_back
#define ALL(v) (v).begin(),(v).end()
#define rsort(v) sort(ALL(v),greater<int>())
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
using namespace std;
int read(){int sum=0,f=1;char c;c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){sum=(sum<<1)+(sum<<3)+(c-'0');c=getchar();}return sum*f;}
void out(int x){if(x<0){x=-x;putchar('-');}if(x>=10)out(x/10);putchar(x%10+'0');}
template <typename T>void die(T s){cout<<s<<endl;exit(0);}
int fast(int a,int b,int P){int res=1;if(P<=0){while(b){if(b&1)res=res*a;a=a*a;b>>=1;}}else{while(b){if(b&1)res=res*a%P;a=a*a%P;b>>=1;}}return res;}
template <typename T>void chkmax(T& a,T b){if(a<b)a=b;return;}
template <typename T>void chkmin(T& a,T b){if(a>b)a=b;return;}
int T,n,ans;
int a[200005],sum[200005],num[400005],lg[200005];
bool sqr(int x){
	if(x==0)return 1;
	int l=1,r=x;
	while(l<=r){
		int mid=l+r>>1;
		if(mid*mid==x)return 1;
		if(mid*mid<x){
			l=mid+1;
		}
		else{
			r=mid-1;
		}
	}
	return 0;
}
bool cnt[400005];
void solve(){
	ans=0;
	vector<int> G;
	n=read();
	cnt[0]=1;G.pb(0);
	rep(i,n){
		a[i]=read();
		sum[i]=sum[i-1]^a[i];
		if(!cnt[sum[i]])G.pb(sum[i]);
		num[sum[i]]++;
		cnt[sum[i]]=1;
	}
	ans=(n+1)*n/2;
	num[0]++;
	cnt[0]=0;
	rep(i,n)cnt[sum[i]]=0;
	int Mx=(1<<lg[n]+1);
	for(int i=0;i<Mx;i++){
		if(sqr(i)){
			for(auto v:G){
				int need=(v^i);
				if(need>v){
					ans=ans-num[need]*num[v];
				}
				else if(need==v){
					ans=ans-num[need]*(num[need]-1)/2;
				}
			}
		}
	}
	repe(i,0,n)num[sum[i]]--;
	cout<<ans<<endl;
	return;
}
void init(){
	for(int i=2;i<=200000;i++)lg[i]=lg[i/2]+1;
	return;
}
signed main(){
	init();
	T=read();
	while(T--)solve();
	return 0;
}

Problem D

数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset! 数组清空不要 memset!

这不比 C 简单!

首先对于这个矩形的我们可以分别用 st 表处理每一行区间最大值,然后我们发现 l 满足单调性,也就是说我们可以二分。二分时,对于每一个左上角,我们可以再开一个 st 表维护向下方和右方分别拓展 l 的最大值,暴力枚举即可。时间复杂度 O(nmlog2n)

点击查看代码
#include<bits/stdc++.h>
#define repe(i,l,r) for(int (i)=l;(i)<=r;(i)++)
#define rep(i,n) for(int (i)=1;(i)<=n;(i)++)
#define FOR(i,r,l) for(int (i)=r;(i)>=l;(i)--)
#define INF 0x3f3f3f
#define pii pair<int,int>
#define mpr make_pair
#define pb push_back
#define ALL(v) (v).begin(),(v).end()
#define rsort(v) sort(ALL(v),greater<int>())
#define lb(v,x) (int)(lower_bound(ALL(v),x)-v.begin())
#define ub(v,x) (int)(upper_bound(ALL(v),x)-v.begin())
#define uni(v) v.resize(unique(ALL(v))-v.begin())
using namespace std;
int read(){int sum=0,f=1;char c;c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){sum=(sum<<1)+(sum<<3)+(c-'0');c=getchar();}return sum*f;}
void out(int x){if(x<0){x=-x;putchar('-');}if(x>=10)out(x/10);putchar(x%10+'0');}
template <typename T>void die(T s){cout<<s<<endl;exit(0);}
int fast(int a,int b,int P){int res=1;if(P<=0){while(b){if(b&1)res=res*a;a=a*a;b>>=1;}}else{while(b){if(b&1)res=res*a%P;a=a*a%P;b>>=1;}}return res;}
template <typename T>void chkmax(T& a,T b){if(a<b)a=b;return;}
template <typename T>void chkmin(T& a,T b){if(a>b)a=b;return;}
bool st;
int T,a[1000006],n,m;
const int N=1000006;
int st1[N][22],st2[N][22],lg[N];
void pre1(){
	for(int i=1;i<=n;i++){
		for(int l=1;l<=lg[m];l++){
			for(int j=1;j+(1<<l)-1<=m;j++){
				st1[(i-1)*m+j][l]=min(st1[(i-1)*m+j][l-1],st1[(i-1)*m+j+(1<<l-1)][l-1]);
			}
		}
	}
	return;
}
int ask1(int l,int r,int p){
	int len=lg[r-l+1];
	return min(st1[(p-1)*m+l][len],st1[(p-1)*m+r-(1<<len)+1][len]);
}
void pre2(int l){
	for(int j=1;j<=m-l+1;j++){
		for(int l=1;l<=lg[n];l++){
			for(int i=1;i+(1<<l)-1<=n;i++){
				st2[(i-1)*m+j][l]=min(st2[(i-1)*m+j][l-1],st2[((1<<l-1)+i-1)*m+j][l-1]);
			}
		}
	}
	return;
}
int ask2(int l,int r,int p){
	int len=lg[r-l+1];
	return min(st2[(l-1)*m+p][len],st2[(r-(1<<len))*m+p][len]);
}
bool check(int l){
	rep(i,n){
		rep(j,m){
			for(int l=0;l<=lg[n];l++){
				st2[(i-1)*m+j][l]=1e9;
			}
		}
	}
	rep(i,n){
		rep(j,m-l+1){
			st2[(i-1)*m+j][0]=ask1(j,j+l-1,i);
		}
	}
	pre2(l);
	rep(i,n-l+1){
		rep(j,m-l+1){
			if(ask2(i,i+l-1,j)>=l)return 1;
		}
	}
	return 0;
}
void solve(){
	rep(i,n){
		rep(j,m){
			for(int l=0;l<=lg[m];l++){
				st1[(i-1)*m+j][l]=1e9;
			}
		}
	}
	n=read(),m=read();
	rep(i,n){
		rep(j,m){
			a[(i-1)*m+j]=read();
		}
	}
	rep(i,n){
		rep(j,m){
			st1[(i-1)*m+j][0]=a[(i-1)*m+j];
		}
	}
	pre1();
	int l=1,r=n,ans=1;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)){
			ans=mid,l=mid+1;
		}
		else{
			r=mid-1;
		}
	}
	cout<<ans<<endl;
	return;
}
void init(){
	lg[1]=0;
	repe(i,2,1000000){
		lg[i]=lg[i/2]+1;
	}
}
bool en;
signed main(){
	init();
	T=read();
	while(T--)solve();
	return 0;
}
posted @   ktq_cpp  阅读(77)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示