ABC 326

AK 了就随便写写,等 cf。

A

按照题意模拟即可。

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=2e5+60,M=2e6+20,mod=998244353;
int n,a,b;

signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>a>>b;
	if(a>=b){
		if(a-b<=3) return cout<<"Yes\n",0;
		else return cout<<"No\n",0; 
	}
	else{
		if(b-a<=2) return cout<<"Yes\n",0;
		else return cout<<"No\n",0; 
	}
	
	return 0;
}

B

暴力扫答案,暴力判断即可。

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=2e5+60,M=2e6+20,mod=998244353;
int n;
inline bool chk(int x){
	int a=x%10,b=(x/10)%10,c=x/100;
	return b*c==a;
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=n;;i++) if(chk(i)) return cout<<i<<'\n',0;
	return 0;
}

C

维护双指针,暴力扫右指针,维护最远可以加入的左边元素即可。

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=3e5+60,M=2e6+20,mod=998244353;
int n,m,a[N];
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	int ans=0;
	for(int i=1,j=1;i<=n;i++){
		while(a[i]-a[j]>=m) j++;
		ans=max(ans,i-j+1);
	}
	cout<<ans<<'\n';
	return 0;
}

D

爆搜加剪枝,首先观察到一个显然的剪枝是每次扫到一个状态都判一下合法性,逐行放置,行的合法性在放的时候就可以满足,能减少不少无用转移,最后扫到的状态在判一下列的 \(A,B,C\) 均只出现一次即可。

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=60,M=2e6+20,mod=998244353;
int n;
char a[N][N];
char R[N],C[N];
bool chk(int x){
	for(int j=1;j<=n;j++){
		for(int i=1;i<x;i++) if(a[i][j]!='.'){
			if(a[i][j]!=C[j]) return 0;else break;
		}
	}return 1;
}
int t[3];
bool Chk(){
	for(int j=1;j<=n;j++){
		t[0]=t[1]=t[2]=0;
		for(int i=1;i<=n;i++){
			if(a[i][j]!='.') t[a[i][j]-'A']++;
		}
//		cout<<t[0]<<t[1]<<t[2]<<'\n';
		if(t[0]!=1||t[1]!=1||t[2]!=1) return 0;
	}
	return 1;
}
void dfs(int x){
	if(!chk(x)) return ;
	if(x>n){
//		cout<<"--------\n";
//		for(int i=1;i<=n;i++){
//			for(int j=1;j<=n;j++){
//				cout<<a[i][j];
//			}cout<<'\n';
//		}
		if(!Chk()) return ;
		cout<<"Yes\n";
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				cout<<a[i][j];
			}cout<<'\n';
		}exit(0);
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			for(int k=j+1;k<=n;k++){
				a[x][i]=R[x];
				if(R[x]=='A'){
					a[x][j]='B';
					a[x][k]='C';
					dfs(x+1);
					a[x][j]='C';
					a[x][k]='B';
					dfs(x+1);
				}
				if(R[x]=='B'){
					a[x][j]='A';
					a[x][k]='C';
					dfs(x+1);
					a[x][j]='C';
					a[x][k]='A';
					dfs(x+1);
				}
				if(R[x]=='C'){
					a[x][j]='A';
					a[x][k]='B';
					dfs(x+1);
					a[x][j]='B';
					a[x][k]='A';
					dfs(x+1);
				}
				a[x][i]=a[x][j]=a[x][k]='.';
			}
		}
	}
} 
signed main(){
//	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	scanf("%s%s",R+1,C+1);
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]='.'; 
	dfs(1);
	cout<<"No\n";
	return 0;
}

E

期望 dp,设 \(f_i\) 表示当前初始 \(x=i\) 的期望工资,转移 \(f_{i}=\sum\limits_{j>i} \dfrac{A_j+f_j}{n}\),后缀和优化转移即可做到 \(O(n)\)

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=3e5+60,M=2e6+20,mod=998244353;
int n,f[N],a[N],s[N];
int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=1ll*res*a%mod;
		a=1ll*a*a%mod;b>>=1; 
	}return res;
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int invn=qpow(n,mod-2);
	for(int i=1;i<=n;i++) s[i]=(s[i-1]+1ll*a[i]*invn%mod)%mod;
	f[n]=0;int sum=0;
	for(int i=n-1;i>=0;i--){
		f[i]=(1ll*s[n]-s[i]+sum+mod)%mod;
		sum=(sum+1ll*f[i]*invn%mod)%mod;
	}
	cout<<f[0]<<'\n';
	return 0;
}

F

首先不难发现的是,奇数操作必然往上下,偶数位置必然往左右,而其往上下还是左右都可以任意选择,变化一下贡献形式,每次相当于背包,折半搜索即可,复杂度 \(O(2^{n/4} \log n)\)

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
//#define int ll
using namespace std;
const int N=2e5+60,M=2e6+20,mod=998244353;
int x,y,n,a[N];
int b[N],totb,c[N],totc;
map<int,int> mpb,mpc;
ll Sb,Sc; 
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>x>>y;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		if(~i&1) b[++totb]=a[i],x+=a[i];
		else c[++totc]=a[i],y+=a[i];
	}
	if(x&1) return cout<<"No",0;
	if(y&1) return cout<<"No",0;
	x/=2,y/=2;
	int limb=min(20,totb);
	for(int i=0;i<(1<<limb);i++){
		int res=0;
		for(int j=0;j<limb;j++) if(i>>j&1){
			res+=b[j+1];
		}
		mpb[res]=i+1;
//		cout<<res<<'\n';
	}
	int limc=min(20,totc);
	for(int i=0;i<(1<<limc);i++){
		int res=0;
		for(int j=0;j<limc;j++) if(i>>j&1){
			res+=c[j+1];
		}
		mpc[res]=i+1;
	}
	int res=0;bool fl=0;
	for(int i=0;i<1<<(totb-limb);i++){
		int res=0;
		for(int j=0;j<(totb-limb);j++) if(i>>j&1){
			res+=b[j+limb+1];
		}
		if(mpb[x-res]){
			Sb=(mpb[x-res]-1)|((ll)i<<limb);
			fl=1;
			break;
		}
	}
	if(!fl) return cout<<"No\n",0;
	fl=0;
	for(int i=0;i<1<<(totc-limc);i++){
		int res=0;
		for(int j=0;j<(totc-limc);j++) if(i>>j&1){
			res+=c[j+limc+1];
		}
		if(mpc[y-res]){
			Sc=(mpc[y-res]-1)|((ll)i<<limc);
			fl=1;
			break;
		}
	}
	if(!fl) return cout<<"No\n",0;
	cout<<"Yes\n";
//	cout<<Sc<<'\n';
	int p=1;
	for(int i=1;i<=n;i+=2){
		int j=(i-1)>>1;
		if(Sc>>j&1){
			if(p) cout<<'L',p=1;
			else cout<<'R',p=1;
		}else{
			if(p) cout<<'R',p=0;
			else cout<<'L',p=0;
		}
		if(i+1<=n){
			if((Sb>>j&1)){
				if(p) cout<<'R',p=1;
				else cout<<'L',p=1;
			}else{
				if(p) cout<<'L',p=0;
				else cout<<'R',p=0;
			}
		} 
	}
	return 0;
}

G

经典网络流题,建模如下:

\(S\xrightarrow{a_i} i\)

\(i\xrightarrow{+\infty} (j,k) ,k<L_{i,j}\)

\((j,k)\xrightarrow{c_j} T\)

考虑这么建模的意义,若在右部点删点,表示选择了右部点升级,贡献 \(-c_i\),没删左部点,表示左部点奖励拿到,贡献 \(a_i\),求最小割。

所以 \(\sum a_i-\text{maxflow}\) 即为所求。

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
#define int ll
#define pb push_back
using namespace std;
const int N=1e6+20,M=2e6+20,Inf=0x3f3f3f3f3f3f3f3fll;
namespace mf{//remember ecnt=1 init
	struct Edge{int v,c,f;}g[M];
	int n,s,t,cur[N],d[N],ecnt=1;
	vector<int> e[N];
	inline void add(int u,int v,int c){g[++ecnt]=(Edge){v,c,0};e[u].pb(ecnt);}
	inline void add_edge(int u,int v,int c){add(u,v,c);add(v,u,0);}
	bool bfs(){
		queue<int> q;
		for(int i=0;i<=n;i++) d[i]=Inf;
		d[s]=0;q.push(s);
		while(!q.empty()){
			int u=q.front();q.pop();
			for(int i:e[u]){
				Edge x=g[i];
				if(d[x.v]==Inf&&g[i].c>g[i].f){
					d[x.v]=d[u]+1;
					q.push(x.v);
				}
			}
		}return d[t]!=Inf;
	}
	int dfs(int u,int a){
		if(!a||u==t) return a;
		int f,flow=0;
		for(int &i=cur[u];i<(int)e[u].size();i++){
			Edge x=g[e[u][i]];
			if(x.c>x.f&&d[x.v]==d[u]+1&&(f=dfs(x.v,min(a,x.c-x.f)))){
				flow+=f;a-=f;g[e[u][i]].f+=f;g[e[u][i]^1].f-=f;
				if(!a) return flow;
			}
		}return flow;
	}
	int solve(){
		int res=0;
		while(bfs()){
			for(int i=0;i<=n;i++) cur[i]=0;
			res+=dfs(s,Inf);
		}return res;
	}
}
int n,m,c[N],a[N],L[60][60];
int sum,id[N][10],cnt,Id[N];
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m;mf::s=0;
	for(int i=1;i<=n;i++) for(int j=1;j<=4;j++) id[i][j]=++cnt;
	for(int i=1;i<=m;i++) Id[i]=++cnt;
	mf::n=++cnt;mf::t=cnt;
	for(int i=1;i<=n;i++) cin>>c[i];
	for(int i=1;i<=m;i++) cin>>a[i];
	for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>L[i][j];
	for(int i=1;i<=m;i++) mf::add_edge(mf::s,Id[i],a[i]),sum+=a[i];
	for(int i=1;i<=n;i++) for(int j=1;j<=4;j++)
		mf::add_edge(id[i][j],mf::t,c[i]);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=L[i][j]-1;k++){
				mf::add_edge(Id[i],id[j][k],Inf);
			}
		}
	}
	cout<<sum-mf::solve()<<'\n';
	return 0;
}```
posted @ 2023-10-28 21:54  Detect-Perplexity  阅读(49)  评论(2编辑  收藏  举报