zoukankan      html  css  js  c++  java
  • YUSS Round 1

    YUSS Round 1

    A. 国庆快乐

    签到题。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int main()
    {
    	printf("Happy 70th Anniversary of People's Republic of China");
    	return 0;
    }
    

    B. 买彩旗

    这道题是一道基本的计算题。不少同学使用float或者double存储钱数,但其实只需要将钱数$ imes10$后再除以单价$ imes10$(即$46$)即可。(被除数和除数同时乘以一个数,商不变)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int a,b;
    
    int main()
    {
    	scanf("%d%d",&a,&b);
    	printf("%d",(a*10+b)/46);
    	return 0;
    }
    

    C. 做作业时间

    这道题同样也考察了基本的计算。
    易知总时间应当是$(c imes60+d)-(a imes60+b)$分钟,那么如何将这个分钟数转化为小时+分钟的形式呢?
    我们知道,在带余除法中:被除数$div$除数$=$商$cdots$余数。
    那么,易知被除数应该是总时间,除数为小时和分钟的进率,$60$。此时,商即为小时数,余数即为分钟数。
    在C++中整除运算可直接使用'/',取模运算可直接使用'%'。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int a,b,c,d;
    
    int main()
    {
    	scanf("%d%d%d%d",&a,&b,&c,&d);
    	printf("%d %d",((c*60+d)-(a*60+b))/60,((c*60+d)-(a*60+b))%60);
    	return 0;
    }
    

    D. 等比数列

    这道题稍有难度,考察了对循环和数学知识的使用。
    因为$nleq30$,所以可以直接用for循环计算;因为$1+2+4+8+cdots+2^{30} leq 2^{31}-1$,所以用int存的下。
    但是循环的方式太过复杂。
    我们可以推导出:
    $sum_{i=0}^{n} 2^{i} = 2^{n+1}-1$
    推导过程如下:
    令$A= sum_{i=0}^{n} 2^i$,

    则$2A=sum_{i=0}^{n} 2^i cdot 2 = sum_{i=0}^{n} 2^{i+1} = sum_{i=1}^{n+1} 2^i$

    所以$A=2A - A = ( sum_{i=1}^{n+1} 2^i) - ( sum_{i=0}^{n} 2^i) = 2^{n+1} - 2^0 = 2^{n+1}-1$
    由此,我们可以得到这道题更为简略的代码。
    在C++中,幂运算可以使用pow函数。使用方法如下:

    pow(a,b)
    

    它等价于$a^b$.

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n,sum;
    
    int main()
    {
    	scanf("%d",&n);
    	sum=pow(2,n+1)-1;
    	printf("%d",sum);
    	return 0;
    }
    

    E.排队接水

    这道题用到的算法叫做贪心。
    小学奥数告诉我们,按接水用时从少到多排队,就能使总等待时间最小。
    所以只需要将所有数据读入后从小到大进行排序即可。
    答案应为:$$frac{sum_{i=1}^{n}T_i(n-i)}{n}(T_1le T_2le T_3le cdots le T_n)$$

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n;
    double ans;
    
    struct node {
    	int num,time;
    }p[1001];
    
    bool cmp(node a,node b) {
    	if(a.time==b.time) {
    		return a.num<b.num;
    	}
    	else {
    		return a.time<b.time;
    	}
    }
    
    void Read() {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) {
    		p[i].num=i;
    		scanf("%d",&p[i].time);
    	}
    }
    
    void Print() {
    	sort(p+1,p+n+1,cmp);
    	for(int i=1;i<=n;i++) {
    		ans+=(n-i)*p[i].time;
    	}
    	ans/=n;
    	printf("%.2lf",ans);
    	return;
    }
    
    int main()
    {
    	Read();
    	Print();
    	return 0;
    }
    

    F. 借教室

    有个算法叫做二分。
    举个例子,你手上有一本书,你要翻到第$x$页,假定你不知道这本书共有多少页,且无法估计这一页在书的几分之几处,那你最快翻到这一页的策略是什么?
    很显然,先翻到一半的位置,看页码比你的目标页码是大了还是小了,然后再选取这本书的前(后)一半,再次对半翻……
    明白这个策略了吗?如果明白了,那恭喜你,你已经学会二分这种算法了。
    但是二分的使用需要一定的前提条件,这个序列必须满足单调性
    但这道题还需要一个叫做差分数列的东西。
    很好理解,是吧。那你把这两样东西放一起拼拼凑凑,这道题就可以了。

    #include<bits/stdc++.h>
    #define N 1000001
    
    using namespace std;
    
    int L,R,mid,n,m;
    int r[N],d[N],s[N],t[N],day[N];
    
    bool Judge(int x) {
    	memset(day,0,sizeof(day));
        for(int i=1;i<=mid;i++) {
            day[s[i]]+=d[i];
            day[t[i]+1]-=d[i];
        }
        if(day[1]>r[1]) {
        	return true;
    	}
        for(int i=2;i<=n;i++) {
            day[i]+=day[i-1];
            if(day[i]>r[i]) {
            	return true;
    		}
        }
        return 0;
    }
    
    long long lower_bound(int l,int r) {
    	while(l<r) {
    		mid=(l+r)/2;
    		if(Judge(mid)) {
    			r=mid;
    		}
    		else {
    			l=mid+1;
    		}
    	}
    	return r;
    }
    
    void Read() {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) {
    		scanf("%d",&r[i]);
    	}
    	for(int i=1;i<=m;i++) {
    		scanf("%d%d%d",&d[i],&s[i],&t[i]);
    	}
    	return;
    }
    
    int main()
    {
    	Read();
    	L=1;
    	R=m;
    	if(m!=lower_bound(L,R)) {
    		printf("-1
    %lld",lower_bound(L,R));
    	}
    	else {
    		printf("0");
    	}
        return 0;
    }
    

    G. 中国高铁

    (个人觉得这是题面写得最好的一道题。)
    这题考了一个分层图。
    简单来说,在未修建任意一条高铁前,你只需关注第$1$层图。
    在修建了一条高铁后,你就将上面一张图中的高铁起点与下面一张图的高铁终点相连,边权为原边权的一半。
    如此,最多有$k+1$张平行的图。
    因为上下平行的各张图都是相同的,所以这并不影响最短路的正确性。
    因为题目不要求要把$k$条高铁都修建完,所以取每张图中$dis[n]$的最小值即可。

    #include<bits/stdc++.h>
    #define N 60
    #define M 3010
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    int n,m,k,cnt,ans=INF;
    int head[N],dis[N][N];
    bool vis[N];
    
    struct node {
    	int now,d,num;
    	bool operator < (const node& rhs) const {
    		return rhs.num<num;
    	}
    };
    
    struct edge {
    	int nxt,to,w;
    }e[M];
    
    void addEdge(int u,int v,int w) {
    	e[++cnt]=(edge){head[u],v,w};
    	head[u]=cnt;
    	return;
    }
    
    void Read() {
    	memset(dis,127,sizeof(dis));
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=m;i++) {
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		addEdge(u,v,w);
    		addEdge(v,u,w);
    	}
    	return;
    }
    
    void Dijkstra() {
    	priority_queue <node> q;
    	dis[1][0]=0;
    	q.push((node){0,0,1});
    	while(!q.empty()) {
    		node t=q.top();
    		q.pop();
    		for(int i=head[t.num];i;i=e[i].nxt) {
    			if(dis[e[i].to][t.now]>t.d+e[i].w) {
    				dis[e[i].to][t.now]=t.d+e[i].w;
    				q.push((node){t.now,dis[e[i].to][t.now],e[i].to});
    			}
    			if(t.now+1<=k) {
    				if(t.d+e[i].w/2<dis[e[i].to][t.now+1]) {
    					dis[e[i].to][t.now+1]=t.d+e[i].w/2;
    					q.push((node){t.now+1,dis[e[i].to][t.now+1],e[i].to});
    				}
    			}
    		}
    	}
    	return;
    }
    
    void Print() {
    	for(int i=0;i<=k;i++) {
    		ans=min(ans,dis[n][i]);
    	}
    	printf("%d",ans);
    	return;
    }
    
    int main()
    {
    	Read();
    	Dijkstra();
    	Print();
    	return 0;
    }
    
  • 相关阅读:
    作业程序
    第十三周完成情况 学生选课管理系统 王杰 孙乾 蔚晓青
    各周任务
    课程设计 学生选课管理 王杰 孙乾 蔚晓青
    第六次作业
    第五次作业
    第四次笔记
    第三次作业
    第二周学习笔记
    JAVA作业
  • 原文地址:https://www.cnblogs.com/luoshui-tianyi/p/11621265.html
Copyright © 2011-2022 走看看