zoukankan      html  css  js  c++  java
  • 牛客算法周周练10 解题报告

    A 论如何出一道水题(思维)

    链接:https://ac.nowcoder.com/acm/contest/5986/A
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld
    题目描述
    给定 n,求一对整数 (i,j),在满足 1 ≤ i ≤ j ≤ n 且gcd(i,j)=1 的前提下,要求最大化 i+j 的值,n<=1e18
    输入描述:
    第一行一个整数 n
    输出描述:
    一行一个整数表示答案
    示例1
    输入
    2
    输出
    3

    题目大意:
    给出一个n,找出1-n中的i,j,使得gcd(i,j)==1的情况下i+j最大。

    解题思路:
    刚开始没有反应过来,一直用的1+n wa了好几发,其实这个题是n和n-1互质,特判一下1的时候ans=2就可以了。AC代码:

    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ll;
    int main()
    {
    	ll n;
    	cin>>n;
    	cout<<(n==1?2:(n+n-ll(1)))<<endl;
    	//system("pause");
    	return 0;
    }
    

    B 暴力出奇迹(二进制贪心)

    在这里插入图片描述
    备注,范围1e5。
    题目大意:
    给出一串长度为n的序列,找一段连续的子序列,使得sum(i,j)* and(i,j)最大化。

    解题思路:
    枚举贪心找最大值的序列,因为涉及到按位与,只要这一位出现0,那么这个结果就会都变成0,于是我们从下一位开始枚举,范围1e5,大约是2^20,枚举a[i]&1的情况就可以了,用ans维护一个最大值,最后输出ans。AC代码:

    #include <iostream>
    #include <algorithm>
    #include <algorithm>
    using namespace std;
    const int _max = 1e5+50;
    typedef long long ll;
    ll a[_max],n;
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    	  cin>>a[i];
    	ll ans=-1;
    	for(int i=0;i<20;i++)//枚举一共20种可能的情况
    	{
    		ll t=a[0],sum=0;
    		for(int j=0;j<n;j++)
    		{
    			if(a[j]>>i&1)//只要出现了0,这一位以后的结果就都是0,重新枚举
    			{
    				sum+=a[j];
    				t&=a[j];
    				ans=max(ans,t*sum);
    			}
    			else
    			{
    				t=a[j+1];
    				sum=0;
    			}
    		}
    	}
    	cout<<ans<<endl;
    	//system("pause");
    	return 0;
    }
    
    

    E 跳石头(二分答案)

    链接:https://ac.nowcoder.com/acm/contest/5986/E
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld
    题目描述
    一年一度的“跳石头”比赛又要开始了!
    这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
    为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。
    输入描述:
    输入文件第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。
    接下来 N 行,每行一个整数,第 i 行的整数 Di(0 < Di < L)表示第 i块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
    输出描述:
    输出文件只包含一个整数,即最短跳跃距离的最大值。
    示例1
    输入
    25 5 2
    2
    11
    14
    17
    21
    输出
    4
    说明
    将与起点距离为 2 和14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离17的岩石跳到距离 21的岩石,或者从距离 21 的岩石跳到终点)。数据范围1e18

    题目大意:
    有一组石头,从起点到终点,计划移走最多m块石头,使得最短跳跃距离最大,输出这个距离。

    解题思路:
    二分答案,每次去判这个长度是不是够m块石头,如果够的话说明距离大了,把距离调小(r=mid-1),如果不够说明距离小了,调大(l=mid+1),让r始终维持一个不合法的边界,那么最后一次r=mid-1的时候就已经合法了,输出r即可。AC代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    const ll _max=0x3f3f3f3f3f3f3f3f;
    int a[N],n,m,final;
    bool countseg(ll mid)
    {
    	ll s=0,ans=0;
    	for(int i=0;i<=n;i++)
    	  if(a[i]-s<mid)
    	  	ans++;
    	  else
    	    s=a[i];
    	if(ans>m)
    	  return true;
    	return false;
    }
    int main()
    {
    	cin>>final>>n>>m;
    	for(int i=0;i<n;i++)
    	cin>>a[i];
    	a[n]=final;
    	sort(a,a+n+1);
    	ll l=0,r=final;
    	while(l<=r)
    	{
    	  ll mid=(l+r)>>1;
    	  if(countseg(mid))
    		r=mid-1;//最后一次r一定是合法的
    	  else
    		l=mid+1;
    	  }
    	cout<<r<<endl;
    	//system("pause");
    	return 0;
    }
    

    F 树上求和(dfs+思维)

    链接:https://ac.nowcoder.com/acm/contest/5986/F
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld
    题目描述
    有一棵包含n个节点和n-1条边的树,规定树链(u,v)为树上从u到v的简单路径。
    树的每条边上都有一个正整数,这个正整数被称作这条边的颜色,规定一条树链的权值w(u,v)为这条树链上所有边的颜色的代数和。
    而整棵树的权值为所有不同的树链的权值的代数和。
    已知所有边的颜色集合恰好为1到n-1这n-1个不同的正整数,请你为每条边安排一种颜色,使得这棵树的权值尽量小,你不需要给出具体方案,只需要求出这个最小的权值即可。
    输入描述:
    测试数据第一行,是一个正整数n(1e5),表示树的节点个数
    接下来n-1行,每行两个用空格隔开的整数u,v,表示树上有一条边连接u和v
    输出描述:
    一个整数,表示了这棵树的最小的权值。
    示例1
    输入
    复制
    4
    1 2
    2 3
    3 4
    输出
    复制
    19
    说明
    w(1,2) + w(1,3) + w(1,4) + w(2,3) + w(2,4) + w(3,4)= 3 + 4 + 6 + 1 + 3 + 2 = 19
    在这里插入图片描述
    题目大意:
    给出一棵树,构建好之后分配每条边的权值,使得最后树上求和的sum值最小。

    解题思路:
    dfs+思维题,通过观察图发现,我们要求的最后答案,就是每条边的权值对答案贡献之和,当前这条边经过的次数=左边节点数*右边节点数,我们将每条边的经过次数存一下,从大到小排序,权值从1往上分配,用vector存一下边,用dfs遍历图,dfs(u,v)的意义是:从u到v的节点有几个,递归的去求解即可。AC代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int _max = 1e5+50;
    vector<ll > vc[_max];
    ll len[_max],cnt=0,n;
    ll dfs(int u,int v)//dfs遍历图求左右节点数
    {
    	ll sum=1;
    	for(int i=0;i<vc[u].size();i++)
    	{
    		if(vc[u][i]!=v)
    		  sum+=dfs(vc[u][i],u);
    	}
    	len[++cnt]=sum*(n-sum);
    	return sum;
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<n;i++)
    	{
    		int u,v;
    		cin>>u>>v;
    		vc[u].push_back(v);
    		vc[v].push_back(u);
    	}
    	dfs(1,0);
    	sort(len+1,len+1+cnt,greater<ll>());//次数排序
    	ll ans=0;
    	for(int i=1;i<=cnt;i++)
    	  ans+=i*len[i];//从1分配权值
    	cout<<ans<<endl;
    	//system("pause");
    	return 0;  
    }
    
  • 相关阅读:
    openjudge 2750
    hexo部署云服务器
    freemaker传输数据问题
    FormData在axios中的骚操作
    Docker安装与初次使用
    docker-compose实现前后端分离的自动化部署
    centos7下设置静态ip
    centos7 安装mariadb 并配置主从复制
    centos7安装solr服务
    centos7安装redis
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294257.html
Copyright © 2011-2022 走看看