IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 杭电第七场 题解 -> 正文阅读

[数据结构与算法]杭电第七场 题解

比赛传送门
作者: fn


签到题

1010题 Smzzl with Tropical Taste / Smzzl与热带风味冰红茶

题目大意
游泳池里有 V V V 升的冰红茶,开始时 V = 1 V=1 V=1升, 主人倒冰红茶的速度是 q V qV qV 升/秒(速度是 V V V 的正比例函数),男孩喝冰红茶的速度是 p V pV pV 升/秒,喝完为止。

给定 p , q p,q p,q ,求解:对于任意 G > 0 G>0 G>0 ,是否存在一个 T > 0 T>0 T>0 ,对于任意 t > T t>T t>T ,男孩在 t t t 秒后喝了超过 G G G 升的冰红茶。

考察内容
数学

分析
p > q p>q p>q 时,喝冰红茶的数量有限;当 p ≤ q p≤q pq 时,喝冰红茶的数量无限。

#include<bits/stdc++.h> // 题1010 
#define ll long long
using namespace std;
ll n,m;
int main(){ 
	ios::sync_with_stdio(0); cin.tie(0);
	int t; cin>>t;
	double p,q;
	while(t--){
		cin>>p>>q;
		if(p<=q){ // 喝无穷大 
			cout<<"N0 M0R3 BL4CK 1CE TEA!"<<endl;
		}
		else{ // 喝有限 
			cout<<"ENJ0Y YOURS3LF!"<<endl;
		}
	}
	return 0;
}

基本题

1008题 Smzzl with Greedy Snake / Smzzl与贪吃蛇

题目大意
Smzzl要为贪吃蛇做一个AI。

在这个游戏中,蛇需要1单位的时间向前移动1单位的长度。 蛇旋转90度也需要1单位的时间。 最初地图上有一种食物。 蛇吃完每一种食物后,下一种食物就出现了。

Smzzl当然希望蛇尽可能快地吃完食物,所以他需要尽量减少蛇吃每一种食物的时间。 请输出一个有效的操作序列。

考察内容
模拟

分析
这道题中只考虑蛇头,蛇没有长度。所以在吃每个食物时尽可能直走,根据食物所在的方向和当前蛇头的方向分类讨论,模拟走最短路径的过程即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+10;
ll n,m,a[N];

int X[4]={0,1,0,-1}, Y[4]={1,0,-1,0};

int main(){ // 已AC
	ios::sync_with_stdio(0); cin.tie(0);
	int t; cin>>t;
	ll x,y,d; 
	while(t--){
		cin>>x>>y>>d;
		cin>>n;
		ll x2,y2;
		for(int i=1;i<=n;i++){
			cin>>x2>>y2;
			ll dx=x2-x,dy=y2-y;
			if(dx>0 && dy>0){ // 右下角 
				if(d==0){ // 头朝右 
					for(int i=1;i<=dy;i++) // 右 
						cout<<'f';
					
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++) // 下 
						cout<<'f';
				}
				else if(d==1){ // 下 
					for(int i=1;i<=dx;i++)
						cout<<'f';
					
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++)
						cout<<'f';
				}
				else if(d==2){ // 左 
					cout<<'u'; d=(d+3)%4; // 变成头朝下 
					for(int i=1;i<=dx;i++)
						cout<<'f';
					
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++)
						cout<<'f';
				}
				else{ // 上 
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dy;i++)
						cout<<'f';
					
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++)
						cout<<'f';
				}
			}
			else if(dx<0 && dy<0){  // 左上角 
				dx=abs(dx),dy=abs(dy);
				if(d==0){ // 头朝右 
					cout<<'u'; d=(d+3)%4;
					
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
				else if(d==1){ // 下 
					cout<<'c'; d=(d+1)%4;
					
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else if(d==2){ // 左 
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else{ // 上 
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
			} 
			else if(dx>0 && dy<0){ // 左下角 
				dx=abs(dx),dy=abs(dy);
				
				if(d==0){ // 头朝右 
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
				else if(d==1){ // 下 
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
				else if(d==2){ // 左 
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else{ // 上 
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
			}
			else if(dx<0 && dy>0){ // 右上角 
				dx=abs(dx),dy=abs(dy);
				
				if(d==0){ // 头朝右 
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else if(d==1){ // 下 
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
					cout<<'u'; d=(d+3)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else if(d==2){ // 左 
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
				else{ // 上 
					for(int i=1;i<=dx;i++) cout<<'f';
					cout<<'c'; d=(d+1)%4;
					for(int i=1;i<=dy;i++) cout<<'f';
				}
				
			}
			else if(dx==0){ // 直线 
				if(dy>0){
					if(d==0){ // 头朝右 
						
					}
					else if(d==1){ // 下 
						cout<<'u'; d=(d+3)%4;
					}
					else if(d==2){ // 左 
						cout<<'c'; cout<<'c'; d=(d+1)%4; d=(d+1)%4;
					}
					else{ // 上 
						cout<<'c'; d=(d+1)%4;
					}
					for(int i=1;i<=dy;i++){
						cout<<'f';
					}
				}
				else{ // dy<0
					dy=-dy;
					if(d==0){ // 头朝右 
						cout<<'c'; cout<<'c'; d=(d+1)%4; d=(d+1)%4;
					}
					else if(d==1){ // 下 
						cout<<'c'; d=(d+1)%4;
					}
					else if(d==2){ // 左 
	
					}
					else{ // 上 
						cout<<'u'; d=(d+3)%4;
					}
					for(int i=1;i<=dy;i++){
						cout<<'f';
					}
				}
			}
			else if(dy==0){
				if(dx>0){
					if(d==0){
						cout<<'c'; d=(d+1)%4;
					}
					else if(d==1){
						
					}
					else if(d==2){
						cout<<'u'; d=(d+3)%4;
					}
					else{ // 3
						cout<<'u'; d=(d+3)%4; cout<<'u'; d=(d+3)%4;
					}
					for(int i=1;i<=dx;i++) cout<<'f';
				}
				else{ // dx<0
					dx=-dx;
					if(d==0){
						cout<<'u'; d=(d+3)%4;
					}
					else if(d==1){
						cout<<'c'; d=(d+1)%4; cout<<'c'; d=(d+1)%4;
					}
					else if(d==2){
						cout<<'c'; d=(d+1)%4;
					}
					else{ // 3
						
					}
					for(int i=1;i<=dx;i++) cout<<'f';
				}
			}
			x=x2;
			y=y2;
		}
		cout<<endl;
	}
	return 0;
}

1007题 Link with Limit / Link与极限

题目大意
Link有一个函数 f ( x ) f(x) f(x) ,其中 x x x f ( x ) f(x) f(x) 都是 [ 1 , n ] [1,n] [1,n] 中的整数。

f n ( x ) = f ( f n ? 1 ( x ) ) f_n(x)=f(f_{n?1}(x)) fn?(x)=f(fn?1?(x)) f 1 ( x ) = f ( x ) f_1(x)=f(x) f1?(x)=f(x) ,关于 x x x 的函数 g ( x ) g(x) g(x) 为:
g ( x ) = lim ? n → + ∞ 1 n ∑ i = 1 n f i ( x ) g (x) =\lim\limits_{n→+∞}\frac{1}{n}∑\limits_{i = 1}^{n}f_i (x) g(x)=n+lim?n1?i=1n?fi?(x)

他想知道对于所有 x ∈ [ 1 , n ] x∈[1,n] x[1,n] , g ( x ) g(x) g(x) 是否相同。

考察内容
数学,图论,dfs

分析
第一步:数学
分析 g ( x ) g (x) g(x) ,其中 f i ( x ) f_i(x) fi?(x) 的意思就是对 x x x 套用 i i i f ( x ) f(x) f(x)
建一张有向图,点 x x x 向点 f ( x ) f(x) f(x) 连边,那么 f f f 迭代的过程实质上是在图上行走的过程。 x x x f ( x ) f(x) f(x) 都是 [ 1 , n ] [1,n] [1,n] 中的整数,所以必然会形成环。 n → + ∞ n→+∞ n+ 时,只有环上的点权才会对极限有影响。原题转化为问每一个环的点权平均值是否相同。

第二步:图论
找出所有环并求出点权平均值。

先连上反向边。利用 dfs 遍历结点找环,找到时计算点权平均值,然后反向遍历所有可以到达这个环的结点,这些结点的 g ( x ) g (x) g(x) 都是相同的,不会对答案造成影响,之后不再遍历。
复杂度 O ( n ) O(n) O(n)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll n,m,f[N],an; // f[i]指向i下一个结点 
vector<int> f2[N]; // 反向边

int loop[N]; // loop[i]==1表示i可以到达已知的环 

double sum=0,ans=0;
double g[N]; //
ll ff[N]; 
int vis[N]; 

void dfs2(int x){ // 遍历反向边 
	if(loop[x]==1)return;
	
	loop[x]=1;
	for(auto e:f2[x]){
		dfs2(e);
	} 
} 

void dfs(int x,ll cnt){ // cnt记录环大小 
    if(an==0)return; // 剪枝 
    
    ff[x]=sum;
    sum+=f[x];
    vis[x]=cnt;
    g[x]=sum;
    if(vis[f[x]]==0){
        dfs(f[x],cnt+1);
        return;
    }
    else{
		dfs2(x); // 标记可以到达环 
    	
        int s=cnt-vis[f[x]]+1;
        if(s==0) return;
        sum=(g[x]-ff[f[x]])*1.0/s;
        //cout<<sum<<" "<<s<<endl;
        
        if(ans==0) ans=sum;
        if(ans!=sum) an=0;
    }
    return;
}

void init(int n){
	memset(g,0,sizeof(g[0])*(n+1));
    memset(ff,0,sizeof(ff[0])*(n+1));
    memset(f,0,sizeof(f[0])*(n+1));
    memset(loop,0,sizeof(loop[0])*(n+1));
    memset(ff,0,sizeof(ff[0])*(n+1));
    memset(vis,0,sizeof(vis[0])*(n+1));
    for(int i=1;i<=n;i++){
        f2[i].clear();
    }
}

int main(){ // AC
    ios::sync_with_stdio(0); cin.tie(0);
    int t; cin>>t;
    while(t--){
    	cin>>n;
		init(n);
        
        an=1;
        ans=0;
        sum=0;
        for(int i=1;i<=n;i++){
            cin>>f[i]; // 正向边 
            f2[f[i]].push_back(i); // 加一条反向边 
        }
        for(int i=1;i<=n;i++){
            if(loop[i]==0){ // 无法到达已知环 
                sum=0;
                dfs(i,1);
            }
        }
        if(an==0) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}
/*
10
6
5 3 3 3 1 4
YES 

10
2 3 4 5 6 7 8 9 10 1
YES
*/

1003题 Fall with Trees / Fall与树

题目大意
Fall想要画一个完美的二叉树。

我们首先规定树中所有具有相同深度的节点在平面上也具有相同的y坐标。 将相同深度的节点定义为相同层次的节点,那么完美二叉树有四个属性。

  • 满二叉树。
  • 相邻两层节点的y坐标差为常数。
  • 同一层次上两个相邻节点的x坐标差为常数。
  • 每个节点的x坐标是其子节点x坐标的平均值。

Fall已经画出了这个二叉树的根节点和它的左右两个子节点。 现在Fall打算画出总共k个层次,他想知道这个完美二叉树的所有节点的凸包的面积是多少。

完美二叉树的例子:
完美二叉树

考察内容
数学,等比数列求和

分析
等比数列求每一层的面积和

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int k,t,x0,y0,x1,y1,x2,y2;

int main(){ //
    cin>>t;
    while(t--){
        scanf("%d",&k);
        scanf("%d%d%d%d%d%d",&x0,&y0,&x1,&y1,&x2,&y2);
        
        ll d=x2-x1,h=y0-y1,S=(2ll*k-5)*d*h,p=60000ll*d*h;
		for (int i=1;i<=k&&p;i++) p>>=1;
		S+=p/10000,p%=10000,k=p%10,p/=10;
		
		printf("%lld.%03lld\n",S,p+(k>=5));	
    }
}

进阶题

1012题 Yiwen with Sqc / Yiwen和字符串

题目大意
定义权值为区间里面每个字母出现次数的平方和,给定一个字符串,计算字符串所有子区间的权值和。

考察内容
差分,字符串,复杂度优化

分析
不同字母之间没有影响,分别考虑每一种字母。

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

const int P = 998244353;
int n;
char ch[200005];

int solve(vector<int> vec){
	vec.push_back(n+1);
	int ans=0,per=0,dif=0;
	for (int i=1;i<vec.size();i++){
		ans=(1ll*ans+1ll*per*(vec[i]-vec[i-1]))%P;
		dif=(1ll*dif+2ll*vec[i-1]+vec[i]-vec[i-1])%P;
		per=(per+dif)%P;	
	}
	return ans;
}

void solve(){
	scanf("%s",ch+1);
	n=strlen(ch+1);
	ch[n+1]='\0';
	vector<int> a[28];
	for (int i=0;i<=25;i++) a[i].push_back(0);
	for (int i=1;i<=n;i++) {
		a[ch[i]-'a'].push_back(i);
	}
	int ans=0;
	for (int i=0;i<=25;i++) {
		ans=(ans+solve(a[i]))%P;
	}
	printf("%d\n",ans);
}
int main(){
	int t;
	scanf("%d",&t);
	while (t--) solve();
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:40:50  更:2021-08-11 12:42:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 17:06:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计