牛客小白月赛33

B:连分数

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

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一个分数可以写成如下连分数的形式:

\frac{P}{Q}=a + \frac{1}{b+\frac{1}{c+\frac{1}{d+…}}}
Q
P

=a+
b+
c+
d+…
1

1

1

现在给你一个分数,你能否将它写成连分数。
输入描述:
首行一个正整数 T,(1 \le T \le 120)T,(1≤T≤120),代表测试数据的组数

接下来 {T}T 行每行给出两个正整数 P,Q, 0 \le P,Q \le 2^{31}-1, Q \neq 0P,Q,0≤P,Q≤2
31
−1,Q


=0

保证输入的分数都可以写成有穷连分数的形式
输出描述:
每组测试数据输出一行,格式见样例
示例1
输入
复制
3
103 24
21 73
4 2
输出
复制
103/24 = 4+1/{3+1/{2+1/3}}
21/73 = 0+1/{3+1/{2+1/10}}
4/2 = 2

主要思路:
模拟数学运算过程
1/即取了倒数y一定比x%y大
反转一下如2/3->1/{1+1/2}

挪酒瓶(待补)

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

题目描述
你有 {N}N 瓶酒,第 {i}i 瓶重量为 w_iw
i

,想要交换到位置 a_ia
i

每次可以选择两个酒瓶,交换他们的位置,花费为两个酒瓶的重量和。

求把所有酒瓶交换到指定位置最小的花费
输入描述:
第一行一个正整数 T, 1 \le T \le 15T,1≤T≤15,代表测试数据的组数

每组测试数据有3行,第一行一个正整数 N, N \le 10^5N,N≤10
5
,表示酒瓶的数量

第二行 {N}N 个正整数 a_ia
i

,表示第 {i}i 个酒瓶想要到 {a_i}a
i

位置上。输入保证 {1}1 到 {N}N 在 {a_i}a
i

中恰出现一次。

第三行{N}N个正整数{w_i}w
i

,表示第{i}i瓶酒的重量为{w_i, 1 \le w_i \le 100}w
i

,1≤w
i

≤100
输出描述:
每组输入数据输出一行,代表花费
示例1
输入
复制
2
4
2 1 4 3
10 20 30 40
3
2 3 1
10 20 30
输出
复制
100
70

#include <iostream>
#include <algorithm>
#include <cstring>
 
using namespace std;
 
const int N = 1e5+10;
 
int a[N], w[N];
bool st[N];
 
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        memset(st, 0, sizeof st);
        int n, ans = 0, min_all = 1e9;
        cin >> n;
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &w[i]);
            min_all = min(min_all, w[i]);
        }
         
        for(int i = 1; i <= n; i++)
            if(!st[i])
            {
                int cnt = 0, minv = 1e9;
                for(int j = i; !st[j]; j = a[j])
                {
                    cnt++;
                    ans += w[j];
                    minv = min(minv, w[j]);
                    st[j] = true;
                }
                ans += min((cnt - 2) * minv, (cnt + 1) * min_all + minv);
            }
        cout << ans << endl;
    }
     
    return 0;
}

D:购物

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

题目描述
有 {S}S 种商品以及每种商品的数量,有 {N}N 个人,已知这 {N}N 个人都已有哪些商品,这些人只会购买他们没有的商品,求这 {N}N 个人购买完成后,剩余的商品种类数
输入描述:
第一行一个正整数 {T, T \le 50}T,T≤50,代表测试数据的组数

每组测试数据的第一行有两个整数 {S,1 \le S \le 100}S,1≤S≤100 和 {N, 1 \le N \le 100}N,1≤N≤100

接下来 {S}S 行每行一个字符串和一个数字表示一个商品

最后 {N}N 行,第 {i}i 行表示第 {i}i 个人已有的商品,每行先给出一个正整数 {k_i}k
i

,代表第 {i}i 个人已有的商品数量,之后有{k_i}k
i

个字符串,代表第 {i}i 个人拥有的商品名称

输入保证所有商品名称长度不超过 {128}128,并且所有商品名称都是以英文字母组成,每种商品的数量不会超过 {1000}1000

输出描述:
对于每组数据在一行中输出一个整数,表示剩余的商品种类数量

若剩余数量为{0}0,请在一行中输出 “Need to be lucky”

示例1
输入
复制
3
5 4
Tshirt 10
Watch 4
Towel 3
HandLight 10
LimitedBook 1
1 Tshirt
1 Tshirt
2 Tshirt Watch
2 Tshirt HandLight
2 2
LimitedCD 1
Handring 1
1 Handring
1 LimitedCD
2 2
ABCDEFGHIJKLMNOPQRSTUVWXYZ 1
abcdefghijklmnopqrstuvwxyz 1
1 ABCDEFGHIJKLMNOPQRSTUVWXYZ
1 ABCDEFGHIJKLMNOPQRSTUVWXYZ
输出
复制
3
Need to be lucky
1
主要思路:
难点就在于如何买走自己没有的
用一下逆向思维,加上自己有的,最后统一减。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        map<string,int> book;
        int n,m,ans=0;
        string a[101];
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            string x;
            int y;
            cin>>x>>y;
            a[i]=x;
            book[x]+=y;
        }
        for(int i=0;i<m;i++)
        {
            int tt;
            cin>>tt;
            while(tt--)
            {
                string aa;
                cin>>aa;
                book[aa]++;
            }
        }
        for(int i=0;i<100;i++)
        {
            if(book[a[i]]>m)
                ans++;
        }
        if(!ans) cout<<"Need to be lucky"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

G:切圆圈

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

题目描述
给定一个环形数组,保证数组元素之和为零,现在允许将数组进行切割,求最多分成多少个总和为零的片段。
输入描述:
输入第一行给出一个正整数 {T,T \le 200}T,T≤200,代表测试数据的组数

每组数据在第一行给出一个整数 {n, n \le 10000}n,n≤10000,然后在第二行给出 {n}n 个整数 A_i, 1 \le \left | A_i\right | \le 10000A
i

,1≤∣A
i

∣≤10000
输出描述:
对于每组输入在一行中输出一个正整数,代表最多片段的个数
示例1
输入
复制
2
4
4 2 -4 -2
5
2 -3 4 -4 1
输出
复制
1
2

主要思路:
主要是一个前缀和的灵活应用
s[i]=s[j]的话 a[i]+……a[j]一定=0

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n,s[100001]={0},x,maxa=0;
        map<ll,ll> book;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            s[i]=s[i-1]+x;
            book[s[i]]++;
            maxa=max(maxa,book[s[i]]);
        }
        cout<<maxa<<endl;
    }
    return 0;
}

H:货物运输

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

题目描述
运输公司提供了许多运输方案,每个方案 P_iP
i

会从一个固定的起始城市 A_iA
i

运送东西到另一个固定的终点城市 B_iB
i

,每运输一箱的货物,你就必须付给运输公司 C_iC
i

哒哒币。另外,若两个方案的终点与起点相接,则可以不花任何额外费用的将货物转过去。不过由于你的运输量太大了,运输公司决定祭出优惠,若用方案 P_iP
i

运输了超过 D_iD
i

箱的可鱼果,多出来的部份每箱改收优惠价 C^,_iC
i
,

哒哒币。
输入描述:
输入的第一行有一个正整数 T,T \le 20T,T≤20 ,代表测试数据的组数。
每组测试数据的第一行有五个正整数 N,N \le 100, M,M \le N \times (N-1)), S, E ,1 \le S,E \le N, F,F \le 10^9N,N≤100,M,M≤N×(N−1)),S,E,1≤S,E≤N,F,F≤10
9
,各一个空白隔开。

{N}N代表可鱼国内有几个城市,{M}M 代表墨鱼运输公司提供几种运输方 案。{S, E}S,E分别代表你的工厂所在的城市以及你所要送去的城市。{F}F代表那隻富有的大可鱼订购了多少箱的货物。

接下来 {M}M行,每行有五个正整数
意思如同叙述中所说。

输出描述:
每组测试数据输出一行,表示最小的花费
示例1
输入
复制
3
4 4 1 4 1
1 2 1 1 1
2 4 5 1 3
1 3 1 1 1
3 4 6 1 1
4 4 1 4 2
1 2 1 1 1
2 4 5 1 3
1 3 1 1 1
3 4 6 1 1
2 1 1 2 999999999
1 2 50216 1000 50216
输出
复制
6
9
50215999949784

主要思路:
最短路问题,记得初始化

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pa;
long long n,m,st,en,sum;
vector<long long> map[101],w[101];
long long dis[101];
bool book[101];
long long d()
{
    memset(dis,0x3f,sizeof(dis));
    priority_queue< pa,vector<pa>,greater<pa> >q;
    dis[st]=0;
    q.push({0,st});
    while(q.size())
    {
        pa now=q.top();
        q.pop();
        long long diss=now.first;
        int sit=now.second;
        if(book[sit]) continue;
        book[sit]=1;
        for(int i=0;i<map[sit].size();i++)
        {
            long long disss=w[sit][i];
            int sitt=map[sit][i];
            if(dis[sitt]>diss+disss)
            {
                dis[sitt]=diss+disss;
                q.push({dis[sitt],sitt});
            }
        }
    }
    return dis[en];
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(book,0,sizeof(book));
        for(int i=1;i<=n;i++)//一定要初始化
        {
            map[i].clear();
            w[i].clear();
        }
        cin>>n>>m>>st>>en>>sum;
        for(int i=0;i<m;i++)
        {
            long long x,y,c1,d1,c2;
            cin>>x>>y>>c1>>d1>>c2;
            map[x].push_back(y);
            long long c;
            if(d1>sum)
            	c=sum*c1;
            else c=d1*c1+(sum-d1)*c2;
          //  cout<<c<<endl;
            w[x].push_back(c);
        }
        cout<<d()<<endl;
        //for(int i=1;i<=n;i++)
         //   cout<<dis[i]<<' ';
      //  cout<<endl;
    }
    return 0;
}

J:线段的交

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

题目描述
给出两条线段,如果有相交求四点围成的四边形面积,否则输出零
输入描述:
输入共四行,每行给出一个坐标,前两行代表第一条线段,后两行代表第二条线段
每行座标都包含了两个实数{x,y}x,y,所有的座标皆满足 -10^4 < x, y < 10^4−10
4
<x,y<10
4
,数值固定精准到小数点下第三位。
输入保证,四个座标一定两两相异,不会有任何一个坐标在另两个坐标的连线上。
输出描述:
在一行中输出一个非负实数表示面积,输出的答案与正确答案误差在 10^{-6}10
−6
内皆视为正确
示例1
输入
复制
2.000 0.000
-1.000 0.000
0.000 1.000
0.000 -1.000
输出
复制
3.0000000
示例2
输入
复制
24.152 31.428
13.505 17.779
14.240 32.285
22.130 12.326
输出
复制
160.0970415000
示例3
输入
复制
1.500 1.500
1.500 -1.500
-1.500 -1.500
-1.500 1.500
输出
复制
0

主要思路:
主要是考查两个重要数学知识
①利用向量积|a||b|sin(正为顺时针转,负为逆时针)
判断是否线段有交点
(有交点的话c,d 一定在ab两端,并且a,b一定在cd两端)
②利用海伦公式求仅知道边长的三角形面积

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
struct point
{
    double x,y;
};
struct line
{
    point a,b;
};
double dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double s(double x,double y,double z)
{
    double sum=(x+y+z)/2;
    return sqrt(sum*(sum-x)*(sum-y)*(sum-z));
}
bool judge(point a,point b,point c,point d)//相交的话一定是两端点在顶点的两端
{
    double f1=((a.x-b.x)*(a.y-c.y)-(a.y-b.y)*(a.x-c.x));
    double f2=((a.x-b.x)*(a.y-d.y)-(a.y-b.y)*(a.x-d.x));
    if(f1*f2<=0) return true;
    return false;
}
bool cross(line l1,line l2)
{
    return (judge(l1.a,l1.b,l2.a,l2.b)&&judge(l2.a,l2.b,l1.a,l1.b));
}
int main()
{
    line l1,l2;
    cin>>l1.a.x>>l1.a.y>>l1.b.x>>l1.b.y;
    cin>>l2.a.x>>l2.a.y>>l2.b.x>>l2.b.y;
    double ans=0;
    if(cross(l1,l2))
    {
        double u,v,w;
        u=dis(l1.a,l1.b);
        v=dis(l1.a,l2.a);
        w=dis(l1.b,l2.a);
        ans+=s(u,v,w);
        u=dis(l2.a,l2.b);
        v=dis(l1.b,l2.a);
        w=dis(l1.b,l2.b);
        ans+=s(u,v,w);
        u=dis(l1.a,l1.b);
        v=dis(l1.a,l2.b);
        w=dis(l1.b,l2.b);
        ans+=s(u,v,w);
        u=dis(l2.a,l2.b);
        v=dis(l1.a,l2.a);
        w=dis(l1.a,l2.b);
        ans+=s(u,v,w);
        printf("%0.8lf\n",ans/2.0);
    }
    else cout<<0<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值