2023 NOI 春季测试

2023 NOI 春季测试

P9117 [春季测试 2023] 涂色游戏

记录每一行/列最后一次被更新的时间和颜色。

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int a[100005],b[100005],ca[100005],cb[100005];
signed main(){
	int T=read();
	while(T--){
		int n=read(),m=read(),q=read();
		for(int i=1;i<=n;i++)ca[i]=a[i]=0;
		for(int j=1;j<=m;j++)cb[j]=b[j]=0;
		for(int i=1,op,x,c;i<=q;i++){
			op=read(),x=read(),c=read();
			if(op==0)a[x]=c,ca[x]=i;
			else b[x]=c,cb[x]=i;
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(ca[i]>cb[j])printf("%lld ",a[i]);
				else printf("%lld ",b[j]);
			}
			puts("");
		}
	}
	return 0;
}

P9118 [春季测试 2023] 幂次

考场上没判 \(k\) 巨大的情况。\(k=1\)\(k>60\) 特判。\(k>2\) 时可以暴力枚举 \(a\)\(k=2\) 时需要和完全平方数做一个容斥,丢到 set 里去重即可。

#include<bits/stdc++.h>
#define int long long
#define i128 __int128
using namespace std;
const int SIZ=1e6,inf=8e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int mysqrt(int x){
	int l=0,r=sqrt(x),ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(mid*mid<=x)ans=mid,l=mid+1;
		else r=mid-1;
	}
	return ans;
}
int mypow(int a,int b){
	int ans=1;
	for(int i=1;i<=b;i++){
		if((i128)ans*a>=inf)return inf;
		ans*=a;
	}
	return ans;
}
signed main(){
	int n=read(),k=read(),ans=0;set<int>s;
	if(k>60)return printf("1"),0;
	if(k==1)return printf("%lld",n),0;
	if(k==2)ans+=mysqrt(n);
	for(int j=k;j<=60;j++){
		for(int i=1;i<=SIZ;i++){
			int x=mypow(i,j);if(x>n)break;
			int y=mysqrt(x);if(k!=2||y*y!=x)s.insert(x);
		}
	}
	printf("%lld",(int)s.size()+ans);
	return 0;
}

P9119 [春季测试 2023] 圣诞树

发现这是一个凸多边形,得到一个性质:两条边不会交叉。如果有交叉,显然交换它们长度会更小。

那么假设从 \(x\) 出发,那么下一步必然走 \(x+1\)\(x-1\),否则遍历回来必然有相交。定义 \(f_{i,j,0}\) 表示 \(i,i+1,i+2\dots j\) 的最短路径,\(f_{i,j,1}\) 表示 \(i,i-1,i-2\dots j\) 的最短路径。有转移式:

\[f_{i,j,0}=\min(\text{dist}(i,i+1)+f_{i+1,j,0},\text{dist}(i,j)+f_{j,i+1,1}) \]

\[f_{i,j,1}=\min(\text{dist}(i,i-1)+f_{i-1,j,1},\text{dist}(i,j)+f_{j,i-1,0}) \]

其中 \(\text{dist}(i,j)\) 表示 \(i,j\) 间的距离,边界是 \(f_{i,i,0/1}=0\)(注意这里我们并没有考虑环形的条件,比如 \(1\rightarrow n\) )。

#include<bits/stdc++.h>
#define int long long
#define db long double
using namespace std;
const db eps=1e-11,inf=1e12;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int n,id;db x[1005],y[1005],f[1005][1005][2];
db dist(int i,int j){
	return sqrtl((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
db dfs(int i,int j,int op){
	if(f[i][j][op]>eps-1.000000000)return f[i][j][op];
	if(i==j)return f[i][j][op]=0.0000000000;
	if(op==0)return f[i][j][op]=min(dist(i,(i+1)%n)+dfs((i+1)%n,j,op),dist(i,j)+dfs(j,(i+1)%n,op^1));
	else return f[i][j][op]=min(dist(i,(i-1+n)%n)+dfs((i-1+n)%n,j,op),dist(i,j)+dfs(j,(i-1+n)%n,op^1));
}
void print(int i,int j,int op){
	printf("%lld ",i+1);
	if(i==j)return;
	if(op==0){
		db tmp1=dist(i,(i+1)%n)+dfs((i+1)%n,j,op);
		db tmp2=dist(i,j)+dfs(j,(i+1)%n,op^1);
		if(fabs(f[i][j][op]-tmp1)<=eps)print((i+1)%n,j,op);
		else print(j,(i+1)%n,op^1);
	}
	else{
		db tmp1=dist(i,(i-1+n)%n)+dfs((i-1+n)%n,j,op);
		db tmp2=dist(i,j)+dfs(j,(i-1+n)%n,op^1);
		if(fabs(f[i][j][op]-tmp1)<=eps)print((i-1+n)%n,j,op);
		else print(j,(i-1+n)%n,op^1);
	}
}
signed main(){
	n=read(),id=0;
	for(int i=0;i<n;i++){
		cin>>x[i]>>y[i];
		if(y[i]-y[id]>eps)id=i;
	}
	for(int i=0;i<n;i++)for(int j=0;j<n;j++)for(int k=0;k<2;k++)f[i][j][k]=-1.000000000;
	db tmp1=dist(id,(id+1)%n)+dfs((id+1)%n,(id-1+n)%n,0);
	db tmp2=dist(id,(id-1+n)%n)+dfs((id-1+n)%n,(id+1)%n,1);
	printf("%lld ",id+1);
	if(tmp1-tmp2<eps)print((id+1)%n,(id-1+n)%n,0);
	else print((id-1+n)%n,(id+1)%n,1);
	return 0;
}

P9120 [春季测试 2023] 密码锁

暂时不会。

posted @ 2023-03-06 16:46  xx019  阅读(316)  评论(0编辑  收藏  举报