牛客小白月赛69

A.蛋挞

题目链接
分析:签到题,其他人分的尽量多且一样那就是n/m,剩下的余数就是牛牛吃的,比较n/m,n%m大小即可。注意数值范围。

#include<bits/stdc++.h>
using namespace std;
long long n,m;
int main()
{
	cin>>n>>m;
	long long a=n/m;
	long long b=n%m;
	if(a>b)
	{
		puts("niuniu eats less than others");
	}
	else if(a<b)
	{
		puts("niuniu eats more than others");
	}
	else puts("same");
	return 0;
}

B.玩具

题目链接
分析:购买两个即可免单较低的那个,那最贵的是必须花钱买的,但是免的可以是任何一个,分析可知免第二贵的是最划算的,同理可证。所以进行排序,如果个数是偶数,那么偶数位的均要花钱,而奇数位免单;如果个数是奇数,那么奇数位花钱,偶数位免单。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
long long n,res;
long long a[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    if(n%2)
    {
        for(int i=1;i<=n;i+=2) res+=a[i];
    }
    else
    {
        for(int i=2;i<=n;i+=2) res+=a[i];
    }
    cout<<res<<endl;
    return 0;
}

C.开题顺序

题目链接
分析:由于这组数据非常小只有9个,而且还是连续的,所以全排列模拟一下即可求出答案。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 20;
int n,tt,k,res,sum;
bool st[N];
struct Node
{
    int a,b,c,x,y;
}p[N];
void dfs(int t,int sum)
{
    res=max(res,sum);
    for(int i=1;i<=n;i++)
    {
       
        if(t+p[i].x<=tt&&!st[i])
        {
            st[i]=true;
            dfs(t+p[i].x,sum+max(p[i].c,p[i].a-(t+p[i].x)*p[i].b-p[i].y*k));
            st[i]=false;
        }
            
    }
    return;
}
signed main()
{
    cin>>n>>tt>>k;
    for(int i=1;i<=n;i++) cin>>p[i].a>>p[i].b>>p[i].c>>p[i].x>>p[i].y;
    dfs(0,0);
    cout<<res<<endl;
    return 0;
}

D.旅游

题目链接
分析:这题几乎为最小生成树的板子,但需要知道一个结论,例如有两条路的损坏值为2和3,先修3再修2会比先修2再修3耗费小,3*1+2*2<2*1+3*2。所以这里采用kruskal板子,然后那个数组记录最小生成数的路径花费,这一定是有序的,再根据上面那个结论先修最大的,直到钱不够就让国家修复即可。如果全修复了输出0就行。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e4+10,M = 1e5+10;
int n,m,c;
int p[N],t[N];
struct Edge
{
    int a,b,w;
}g[M];
bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
int find(int x)
{
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
void kruskal()
{
    sort(g+1,g+m+1,cmp);
    for(int i=1;i<=n;i++) p[i]=i;
    int cnt=0;
    for(int i=1;i<=m;i++)
    {
        int a=g[i].a,b=g[i].b,w=g[i].w;
        int pa=find(a),pb=find(b);
//         printf("a---%d pa---%d,b---%d pb---%d,w---%d\n",a,pa,b,pb,w);
        if(pa!=pb)
        {
            p[pa]=p[pb];
            t[++cnt]=w;
        }
    }
//     for(int i=1;i<=cnt;i++) printf("%d ",t[i]);
//     puts("");
    for(int i=cnt,k=1;i>=1;i--,k++)
    {
        c-=k*t[i];
        if(c<0)
        {
            cout<<t[i]<<endl;
            return;
        }
    }
    puts("0");
}
signed main()
{
    cin>>n>>m>>c;
    for(int i=1;i<=m;i++)
    {
        int a,b,w;
        cin>>g[i].a>>g[i].b>>g[i].w;
    }
    kruskal();
}

E.等腰三角形(easy)

题目链接
分析:由于数据范围很小,暴力枚举即可。复杂度为o( n 3 n^3 n3)。别忘了排除三点共线的情况。

#include<bits/stdc++.h>
using namespace std;
const int N = 500;
int n,res;
struct Node
{
    int x,y;
}a[N];
int d(Node a,Node b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool check1(Node a,Node b,Node c)
{
    if((c.x-b.x)*(b.y-a.y)==(c.y-b.y)*(b.x-a.x)) return false;
    return true;
}
bool check2(Node a,Node b,Node c)
{
    if(((d(a,b)==d(a,c)||d(a,b)==d(b,c)||d(a,c)==d(b,c))&&check1(a,b,c))) return true;
    return false;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            for(int k=j+1;k<=n;k++)
            {
                if(check2(a[i],a[j],a[k])) res++;
            }
        }
    }
    cout<<res<<endl;
    return 0;
}

F.等腰三角形(hard)

题目链接
分析:枚举每个点当顶点,然后以边长进行枚举,统计所有边长相等的边,进行边记录边相加,最终得出的结果和从这些相等里面选出两条的选法数是相等的,最后和上一题一样要排除共线,那个sum来存储,根据两点可以求出对称点的位置,如果有就sum++,由于对称会被枚举两次,最后结果需要除以2。注意偏移量的大小。

#include<bits/stdc++.h>
using namespace std;
const int N = 3010,M = 2e6+10,Base = 1500;
int n;
int cnt[M];
int x[N],y[N];
bool st[N][N];
int dis(int a,int b)
{
    return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) 
    {
        cin>>x[i]>>y[i];
        st[x[i]+Base][y[i]+Base]=true;
    }
    long long res=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            res+=cnt[dis(i,j)];
            cnt[dis(i,j)]++;
            if(st[2*x[i]-x[j]+Base][2*y[i]-y[j]+Base]) sum++;
        }
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            cnt[dis(i,j)]=0;;
        }
    }
    cout<<res-sum/2<<endl;
    return 0;                                                                                                        
}

补题仅到此为止,最后一题脑瓜子转不动了。如果有错误欢迎纠正。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值