zoukankan      html  css  js  c++  java
  • 2019-2020Nowcoder Girl初赛题解

    复现链接:https://ac.nowcoder.com/acm/contest/3405#question

    shzr题解:https://www.cnblogs.com/shzr/p/12018915.html

    echozhou题解:https://www.cnblogs.com/EchoZQN/p/12030689.html

    A.牛妹爱整除

    输入3输出10,输入5输出16,盲猜一发3n+1,看了第三个样例输入9输出10,陷入沉思。

    开始推断发现n+1进制符合,理由如下:

    假设为n+1进制的cba,转换为十进制后为下式

    (n+1)*a+(n+1)*(n+1)*b+(n+1)*(n+1)*(n+1)*c

    mod的性质:(a*b*c)%n=[(a%n)*(b%n)*(c%n)]%n

    而(n+1)%n=1,故原式%n=1*a+1*1*b+1*1*1+c=a+b+c

    任意n+1进制的数同理,1+kn(k>=1)进制的数同理,因为(1+kn)%n=1

    要注意如果输出不是n+1,需要开long long,因为n的范围是1e9

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

    B.吃桃

    dp[i]表示i节点向子树内能延伸的最长路径

    dep[i]表示i节点到k节点的距离,初始假定dep[k]=1

    dfs记录深度

    redfs逆dp,输出路径

    样例:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x3f3f3f3f
    const int maxn=1e5+10;
    vector<int> vec[maxn];
    int dp[maxn],dep[maxn];
     
    void dfs(int x)
    {
        int size=vec[x].size();
        for(int i=0;i<size;i++)
        {
            int tmp=vec[x][i];
            if(dep[tmp])continue;//不能只当作vis来判断是否出现过,下面要用到dep 
            dep[tmp]=dep[x]+1;
            dfs(tmp);
            dp[x]=max(dp[x],dp[tmp]);
        }
        dp[x]++;//加上x点本身 
    }
     
    void redfs(int x)
    {
        printf("%d
    ",x);
        if(dp[x]==1)return;
        int size=vec[x].size(),ans=inf;
        for(int i=0;i<size;i++)
        {
            int tmp=vec[x][i];
            if(dep[tmp]<dep[x])continue;
            if(dp[tmp]+1==dp[x])ans=min(ans,tmp);//优先选择节点最小的 
        }
        redfs(ans);
    }
     
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        dep[k]=1;
        dfs(k);
        redfs(k);
        /*
         for(int i=1;i<=n;i++)
        {
            cout<<i<<" "<<dp[i]<<" "<<dep[i]<<endl;
        }*/
        return 0;
    }

    C.背包问题

    代码很简单但是我想了很久

    范围n<=200,V、v[i]<=1e6,w[i]<=200

    题意:总体积不小于V的最小价值

    转换:总体积不大于Vall-V的最大价值(开不了这么大的数组)

    再次转换:对价值进行dp,dp[i]表示同价值最大体积,从价值1到最大价值,存在不小于V体积dp[i],此时的价值i即为答案

    #include<bits/stdc++.h>
    using namespace std;
    const int maxv=1e6+10;
    const int maxw=200+10;
    
    int v[maxw],w[maxw],dp[maxv];//dp[i]表示价值是i的情况下的最大体积
    int main()
    {
        int n,V,sum=0;
        scanf("%d%d",&n,&V);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&v[i],&w[i]);
            sum+=w[i];
        }
     
        for(int i=1;i<=n;i++)
        {
            for(int j=sum;j>=w[i];j--)
            {
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }
        }
     
        //找到第一个满足体积不小于V的价值
        for(int i=1;i<=sum;i++)
        {
            if(dp[i]>=V)
            {
                printf("%d
    ",i);
                break;
            }
        }
        return 0;
    }

    D.泡面

    单调队列giao一下

    加入了自己领悟的代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    pair<int,int> a[maxn];
    struct cmp
    {
        bool operator()(int a,int b)
        {
            return a>b;
        }
    };
    
    int main()
    {
        int n,p;
        long long ans[maxn]={0};
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].first);
            a[i].second=i;
        }
        sort(a+1,a+n+1);
        
        priority_queue<int,vector<int>,cmp> q;//id小的优先 
        //priority_queue<int,vector<int>,greater<int> > q;
        
        long long cur=0;
        for(int i=1;i<=n;i++)//保证Push n个数 
        {
            while(!q.empty()&&cur<a[i].first)//如果打水队列不空,而且还没轮到a[i]打水(a[i]已经为升序) 
            {
                int id=q.top();//就不停地让队列里第一个人去打水 
                q.pop();
                
                //cout<<id<<" "<<cur<<" "<<a[i].first<<endl;
                cur+=p;
                ans[id]=cur; 
            }
            q.push(a[i].second);//a[i]排队
            if(cur<a[i].first)cur=a[i].first;
            //如果a[i]前面的人都打过水了,cur还没轮到a[i],cur之间变成a[i]的时间 
        }
        
        //for一遍后n个人肯定都已经排过队了,把还没打水的排一遍队 
        while(!q.empty())
        {
            int id=q.top();
            q.pop();
            cur+=p;
            ans[id]=cur;
        }
        for(int i=1;i<=n;i++)
        {
            cout<<ans[i]<<" ";
        }
        return 0;
    }

    E.伪直径

    在树上找两条不相同的路径,使得两路径的交最长

    树上最长的路径为直径,该路径少取一个节点后产生的新路径,与直径相交,长度刚好为n-1

    为啥不是n?

    反证法:假设答案为n(直径),即树上存在两条不相同的路径,他们的交为n,因为两条路不同,所以肯定有至少一条路在除了交的部分还有边,那树上最长的路就大于n了,与原假设矛盾。

    故答案不为n。

    剩下就是怎么求树的直径了...

    不学不知道,树形dp原来so easy?:)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    vector<int> vec[maxn];
    int vis[maxn],dp[maxn],ans;
    //dp[i]为以i为起点的最长链的长度 
    void dfs(int u)
    {
        vis[u]=1;
        int size=vec[u].size();
        for(int i=0;i<size;i++)
        {
            int now=vec[u][i];
            if(vis[now])continue;
            dfs(now);
            //cout<<u<<" "<<now<<endl;
            ans=max(ans,dp[u]+dp[now]+1);
            //在u为根节点时,经过u的最长链长度等于它的任意两个子节点的d[i]之和的最大值+1
            //每个u都会遍历一遍,所以可以求出ans 
            dp[u]=max(dp[u],dp[now]+1);
        
        }
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        dfs(1);
        cout<<ans-1<<endl; 
        return 0;
    }
    /* 
    7 
    1 2
    2 6
    2 3
    3 4
    3 5
    5 7 
    */ 

    F.最大最小差

    先mark,有空了滚回来补题

  • 相关阅读:
    linq to entity group by 时间
    Entity Framework Core for Console
    EF Core 多个DbContext迁移命令
    .net for TCP服务端 && 客户端
    创建Windows Service
    EF Code First 快速创建
    在Docker中创建Mongo容器的后续设置
    Docker入门
    Python之collections.defaultdict
    Hough transform(霍夫变换)
  • 原文地址:https://www.cnblogs.com/myrtle/p/12070920.html
Copyright © 2011-2022 走看看