2023牛客寒假算法基础集训营1

ACDEFGHKLM 题解:

A World Final? World Cup! (I)

模拟即可

#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        string s;
        cin>>s;
        int aa=0,bb=0;
        s=" "+s;
        int ans=1;
        bool ok=false;
        for(int i=1;i<=10;i++)
        {
            if(i%2==1)
            {
                if(s[i]=='1')
                    aa++;
                if(aa>bb+5-ans+1)
                {
                    cout<<i<<"\n";
                    ok=true;
                    break;
                }
                if(aa+5-ans<bb)
                 {
                    cout<<i<<"\n";
                    ok=true;
                    break;
                }                   
            }
            else
            {
                if(s[i]=='1')
                    bb++;
                if(bb>aa+5-ans)
                    {
                        cout<<i<<"\n";
                        ok=true;
                        break;
                    }
                if(bb+5-ans<aa)
                     {
                        cout<<i<<"\n";
                        ok=true;
                        break;
                    }                   
                ans++;
            }
        }
        if(!ok)
            {
                if(aa!=bb)
                    cout<<10<<"\n";
                else 
                    cout<<-1<<"\n";
            }
    }
    return 0;
}

C现在是,学术时间 (I)

直接模拟,或者看出来一人一篇文章即可

#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        int ans=0;
        int i=n+1; 
        int sum=n;
        for(int j=1;j<=n;j++)
        {
            if(a[j]!=0)
            {
                i=j;
                sum-=j-1;
                break;
            }
        }
        while(i<=n)
        {
            if(sum-a[i]>=0)
            {
                ans+=a[i];
                sum-=a[i];
                i+=a[i];
            }
            else
            {
                ans+=min(sum,a[i]);
                break;
            }
        }
        cout<<ans<<"\n";
    }
    return 0;
}

D现在是,学术时间 (II)

分类讨论即可,每次选四个顶点作为另一个顶点判断最值

#include<bits/stdc++.h>
using namespace std;
double x,y,xp,yp;
int t;
double iou;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>x>>y>>xp>>yp;
        if(xp==x&&(yp==0||yp==y))
        {
            iou=1;
        }
        else if(yp==y&&(xp==0||xp==x))
        {
            iou=1;
        }
        else if(xp<=x&&yp<=y)
        {
            iou=max(xp*(y-yp),max(xp*yp,max((x-xp)*yp,(x-xp)*(y-yp))));
            iou/=(x*y);
        }
        else if(xp>x&&yp>y)
        {
                iou=(x*y)/(xp*yp);
        }
        else if(xp>x)
        {
            iou=max((x*(y-yp))/(x*y+(xp-x)*(y-yp)),(x*yp)/(x*y+(xp-x)*yp));
        }
        else if(yp>y)
        {
            iou=max((xp*y)/(x*y+xp*(yp-y)),((x-xp)*y)/(x*y+(x-xp)*(yp-y)));
        }
        else
        {
            iou=(x*y)/(xp*abs(yp-y));
        }
        cout<<fixed<<setprecision(9)<<iou<<"\n";
    }
    return 0;
}

E鸡算几何

题解:(借鉴题解 | #2023牛客寒假算法基础集训营1#_牛客博客 (nowcoder.net)

首先把初始状态和最终状态的中点(B)平移至原点,然后将其中初始状态和最终状态的同一条边旋转至同一条坐标轴的同一个方向上,我选的(应该)是y轴正方向(由于边长不同,需要把边进行对应,也就是交换初始状态或最终状态的A、C点,体现在vector上就是翻转),最后考虑两种状态下的剩下一个点是否在y轴同侧,是就说明不一定需要操作三,否则必须使用操作三。

#include <bits/stdc++.h>
using namespace std;
using point_t=long double;  
constexpr point_t eps=1e-8;
constexpr long double PI=3.1415926535897932384l;
template<typename T> struct point{
    T x,y;
    bool operator==(const point &a) const {return (abs(x-a.x)<=eps && abs(y-a.y)<=eps);}
    bool operator<(const point &a) const {if (abs(x-a.x)<=eps) return y<a.y-eps; return x<a.x-eps;}
    bool operator>(const point &a) const {return !(*this<a || *this==a);}
    point operator+(const point &a) const {return {x+a.x,y+a.y};}
    point operator-(const point &a) const {return {x-a.x,y-a.y};}
    point operator-() const {return {-x,-y};}
    point operator*(const T k) const {return {k*x,k*y};}
    point operator/(const T k) const {return {x/k,y/k};}
    T operator*(const point &a) const {return x*a.x+y*a.y;}  
    T operator^(const point &a) const {return x*a.y-y*a.x;}  
    int toleft(const point &a) const {const auto t=(*this)^a; return (t>eps)-(t<-eps);} 
    T len2() const {return (*this)*(*this);} 
    T dis2(const point &a) const {return (a-(*this)).len2();}  
    long double len() const {return sqrtl(len2());}  
    long double dis(const point &a) const {return sqrtl(dis2(a));} 
    long double ang(const point &a) const {return acosl(max(-1.0l,min(1.0l,((*this)*a)/(len()*a.len()))));} 
    point rot(const long double rad) const {return {x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)};} 
    point rot(const long double cosr,const long double sinr) const {return {x*cosr-y*sinr,x*sinr+y*cosr};} 
};
using Point=point<point_t>;
int main(){
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
    cin>>T;
    while(T--){
        vector<Point> s(3),t(3);
        for(auto &[x,y] : s){
            cin>>x>>y;
        }
        for(auto &[x,y] : t){
            cin>>x>>y;
        }
        if(abs(s[1].dis2(s[0]) - s[1].dis2(s[2])) <= eps) goto no;
        if(abs(s[1].dis2(s[0]) - t[1].dis2(t[0])) > eps) reverse(t.begin(), t.end());
        {
            auto [dx,dy] = s[1];
            for(auto &[x,y] : s){
                x -= dx;
                y -= dy;
            }
            auto d = s[1].dis(s[0]);
            auto si = s[0].x/d , co = s[0].y/d;
            for(auto &x : s){
                x = x.rot(co,si);
            }
        }
        {
            auto [dx,dy] = t[1];
            for(auto &[x,y] : t){
                x -= dx;
                y -= dy;
            }
            auto d = t[1].dis(t[0]);
            auto si = t[0].x/d , co = t[0].y/d;
            for(auto &x : t){
                x = x.rot(co,si);
            }
        }
        if(t[2].x*s[2].x<0 || t[2].y*s[2].y<0) goto yes;
        else goto no;
        if(0) yes: cout<<"YES"<<endl;
        if(0) no:  cout<<"NO"<<endl;
    }
    return 0;
}

F鸡玩炸蛋人

由于图不一定联通,那么当有不同联通块里都有ci!=0时,则输出0,最后还剩下ci全为0或者ci!=0的情况在同一个联通块里面,当ci全为0的时候,答案为每个连通块的大小的平方之和,当ci!=0的情况在同一个连通块里面时,答案为这个连通块的大小的平方。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,m,c[N],ss[N];
struct DSU {
    std::vector<int> f, siz;
    DSU(int n) : f(n), siz(n, 1) { std::iota(f.begin(), f.end(), 0); }
    int leader(int x) {
        while (x != f[x]) x = f[x] = f[f[x]];
        return x;
    }
    bool same(int x, int y) { return leader(x) == leader(y); }
    bool merge(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (x == y) return false;
        siz[x] += siz[y];
        f[y] = x;
        return true;
    }
    int size(int x) { return siz[leader(x)]; }
};
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    DSU dsu(n+10);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        dsu.merge(x,y);
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>c[i];
        int fx=dsu.leader(i);
        ss[fx]+=c[i];
        sum+=c[i];
    }
    vector<bool>st(n+10,false);
    if(sum==0)
    {
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int xx=dsu.leader(i);
            if(!st[xx])ans+=dsu.size(xx)*dsu.size(xx);
            st[xx]=true;
        }
        cout<<ans;
        return 0;
    }
    else
    {
        for(int i=1;i<=n;i++)
        {
            int xx=dsu.leader(i);
            if(ss[xx]==sum)
            {
                cout<<dsu.size(xx)*dsu.size(xx);
                return 0;
            }
        }
        cout<<0;
    }
}

G鸡格线

线段树,观察到每个数经过几次fx之后会变成一个不变值,然后用标记来标记是否是不变值。

//线段树4(结构体线段树,懒标记下传)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
int a[maxn];
int n,m;
struct tree
{
    int l,r;
    long long sum;
    bool lazy;
}t[4*maxn+2];
void bulid(int p,int l,int r)
{
    t[p].l=l;t[p].r=r;
    if(l==r)
    {
        t[p].sum=a[l];
        t[p].lazy=false;
        return;
    }
    int mid=l+r>>1;
    bulid(p*2,l,mid);
    bulid(p*2+1,mid+1,r);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
    t[p].lazy=(t[p*2].lazy&&t[p*2+1].lazy);
}
//区间修改[x,y]
void update(int p,int x,int y,int z,int k){
    if(x<=t[p].l && y>=t[p].r)
    {
        if(t[p].lazy)return ;
        if(t[p].l==t[p].r)
        {
            int summ=t[p].sum;
            for(int i=1;i<=k;i++)
            {
                int next=round(10*sqrt(summ));
                if(next==summ)
                {
                    t[p].lazy=true;
                    break;
                }
                summ=next;
            }
            t[p].sum=summ;
            return ;
        }
    }
    int mid=t[p].l+t[p].r>>1;
    if(x<=mid) update(p*2,x,y,z,k);
    if(y>mid) update(p*2+1,x,y,z,k);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
    t[p].lazy=(t[p*2].lazy&&t[p*2+1].lazy);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    bulid(1,1,n);
    while(m--)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int ll,rr,kk;
            cin>>ll>>rr>>kk;
            update(1,ll,rr,0,kk);
        }
        else
            cout<<t[1].sum<<"\n";
    }
    return 0;
}

H本题主要考察了DFS

诈骗题,直接算出总的1和2计算min然后用10去直接减

#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
void dfs(int x,int y)
{
    
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n;
        string s;
        vector<int>v[n*n+10];
        for(int i=1;i<=n*n-1;i++)
        {
            cin>>s;
            for(int j=0;j<s.size();j++)
            {
                v[i].push_back(s[j]-'0');
            }
        }
        int aa=0,bb=0;
        for(int i=1;i<=n*n-1;i++)
        {
            for(auto x:v[i])
            {
                if(x==1)
                    aa++;
                if(x==2)
                    bb++;
            }
        }
        if(aa==bb)
        {
            cout<<10<<"\n";
        }
        else if(aa<bb)
        {
            cout<<10-(bb-aa)<<"\n";
        }
        else
        {
            cout<<10+(aa-bb)<<"\n";
        }
        
    }
    return 0;
}

K本题主要考察了dp

直接构造100100......这样的字符串,可以保证坏区间最少,不需要dp

#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N],m;
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--)
    {
        cin>>n>>m;
        int cnt=n-m;
        int ans=n-2;
        cnt/=2;
        if(cnt==0)
        {
            cout<<n-2;
            return 0;
        }
        m-=cnt;
        if(m<=0)
            cout<<0;
        else 
            cout<<m-1;
    }
    return 0;
}

L本题主要考察了运气

求期望即可,为32

M本题主要考察了找规律

dp求即可

#include<bits/stdc++.h>
using namespace std;
double n,m;
double f[1000];
 signed main()
{
    scanf("%lf%lf",&n,&m);    
     for(int i=1;i<=n;++i)
        for(int j=m;j;--j)
            for(int k=1;k<=j;++k)
                f[j]=max(f[j],f[j-k]+(1.0*k/(1.0*j)));
    printf("%.8lf",f[int(m)]);

    return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值