Dytechlab Cup 2022

Dytechlab Cup 2022

A
过太慢了 QAQ 。看来得多练(可能是因为刚上完数模,脑子一团浆糊)

#include<bits/stdc++.h>
using namespace std;
char ans[105];
int cnt[28];
int main(){
	int t;cin>>t;
	while(t--){
		int n,k;cin>>n>>k;
		string s;cin>>s;
		for(int i=0;i<27;++i)cnt[i]=0;
		for(int i=0;i<k;++i)ans[i]='a';
		for(int i=0;i<n;++i)cnt[s[i]-'a']++;
		for(int i=0;i<26;++i){
			for(int j=0;j<k;++j){
				if(cnt[i]<=0)break;
				if(ans[j]-'a'==n/k)continue;
				if(ans[j]-'a'==i){
					--cnt[i];++ans[j];
				}
			}
		}
		for(int i=0;i<k;++i){
			ans[i]=max(ans[i],'a');
			cout<<ans[i];
		}
		cout<<endl;
	}
	return 0;
}

B
好题!
很好想,公式很自然,但就是卡了 30min,甚至我都想弃赛了。

注意大数开 sqrt 精度损失严重!! (其实小的数也一样)所以能不用 double 就不用。

#include<bits/stdc++.h>
using namespace std;

long long work(long long r){
	if(r==0)return 0;
	long long sq=sqrt(r),ans,now;
	if((sq+1)*(sq+1)<=r)++sq;
	if(sq*sq>r)--sq;
	ans=3*(sq-1);
	now=sq;
	if(sq*(sq+1)<=r)++now;
	if(sq*(sq+2)<=r)++now;
	ans+=now-sq+1;
	return ans;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		long long l,r;
		cin>>l>>r;
		cout<<work(r)-work(l-1)<<endl;
	}
	return 0;
}

C

我觉得样例提示得已经够明显了。。。最小操作单元就是平移 2 个单位。
但这样可能会出错,但样例也十分良心地提醒了:
L 形中间点在棋盘四个角落时,无法整体平移,只能单独一行或一列。

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-48;c=getchar();
	}
	return x*f;
}
int main(){
	int t;cin>>t;
	while(t--){
		int n,fl=0;cin>>n;
		int r1=read(),c1=read(),r2=read(),c2=read(),r3=read(),c3=read();
		int x=read(),y=read();
		int xx=r1,yy=c1;
		if(r2==r3)xx=r2;if(c2==c3)yy=c2;
		if((xx==1||xx==n)&&(yy==1||yy==n)){
			if(x==xx||y==yy)cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
			continue;
		}
		if((x-r1)%2==0&&(y-c1)%2==0)fl=1;
		if((x-r2)%2==0&&(y-c2)%2==0)fl=1;
		if((x-r3)%2==0&&(y-c3)%2==0)fl=1;
		if(fl)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
}

D
(比赛时太困了,想了 5 分钟直接弃疗。

这道题关键在于转化题意:即一步操作相当于用 wi 的代价把第 i 条边的一个端点沿着已有的边转移。若是形成自环,就相当于合并端点。
这时我们考虑最后从 1n 的最短路径,容易(完全想不到)发现,若是由 2 条边组成,那么可以只用 w 最小的边来连,最终代价更小。所以最后的答案路径一定是单独一条边。
这时,又有新的疑问了:如何移动呢?是通过初始边还是某条已经移动过的边呢?
还是考虑最简单的情况:假设有 ij 两条边,目标是移动 i 来作为最终答案,但途中先移动了 j ,然后再让 i 通过 j 来移动。这个假设的前提是 j 移动比不移动更优,即 wi>wj
那么容易发现,因为 wj<wi ,那么完全可以让 ji 走过的路,最终答案还更小。
所以构造方法呼之欲出:预处理出 1n 到所有点的最短距离 dis[i][j],枚举所有边,计算即可。

但自环有什么用?

那当然是先移动一个端点到某个点,然后让另一个端点 “飞” 过来,之后再分开走。这样就节省了一段距离!至于为什么只合并一次,就留给读者了(

(虽然但是,为什么 弗洛伊德 都能写错 QAQ

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';c=getchar();
	}
	return x*f;
}
#define N 505
#define inf 100000000000
long long dis[N][N],w[250005];
int u[250005][2];
int main(){
	int t=read();
	while(t--){
		int n=read(),m=read();
		for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)dis[i][j]=inf;
		for(int i=1;i<=n;++i)dis[i][i]=0;
		for(int i=1;i<=m;++i){
			u[i][0]=read(),u[i][1]=read(),w[i]=read();
			dis[u[i][0]][u[i][1]]=min(dis[u[i][0]][u[i][1]],1ll);
			dis[u[i][1]][u[i][0]]=min(dis[u[i][1]][u[i][0]],1ll);
		}
		for(int k=1;k<=n;++k){
			for(int i=1;i<=n;++i){
				for(int j=1;j<=n;++j){
					dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
				}
			}
		}
		long long ans=10000000000000000;
		int fl=0;
		for(int i=1;i<=m;++i){
			for(int xo=0;xo<2;++xo){
				int x=u[i][xo],y=u[i][xo^1];
				if(dis[1][x]!=inf&&dis[y][n]!=inf){
					ans=min(ans,1ll*(dis[1][x]+dis[y][n]+1)*w[i]);
					fl=1;
				}
				for(int mi=1;mi<=n;++mi){
					if(dis[x][mi]!=inf&&dis[mi][1]!=inf&&dis[mi][n]!=inf){
						fl=1;
						ans=min(ans,1ll*(dis[x][mi]+dis[mi][1]+dis[mi][n]+2)*w[i]);
					}
				}
			}
		}
		if(fl==0)cout<<dis[1][n]<<endl;
		printf("%lld\n",ans);
	}
	return 0;
}
		
	
posted @   Mystletainn  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示