• 牛客小白月赛#56 A~F


    牛客小白月赛#56

    A.阿宁的柠檬

    • 题意

      • 甜度的分值范围为0a,酸度的分值范围为1b
      • 有n个柠檬,求最小分值和最大分值
    • 题解

      • 最小值为甜度取0,酸度取1,分值为0*n+1*n;最大值为甜度,酸度取a,b,分值为a*n+b*n
    • 代码

    #include 
    
    using namespace std;
    
    int main() {
        long long a,b,n;//注意爆int
        cin>>a>>b>>n;
        cout<<n<<' '<<(a+b)*n<<'\n';
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    B.阿宁与猫咪

    • 题意

      • 给定值m;构造一个正整数数列,元素之和为m,且奇数位置之积 与 偶数位之积 的和最小
    • 题解

      • 猜测结论:构造的数列是m个1
      • 证明上述结论成立:全为1时,其奇数位积于偶数位积之和必然为2(m!=1时);其他的构造也就是要替换掉某些1变成不是1的元素,那么必然奇数位或者偶数位积>1,那么之和>2,所以可以证得,上述方案为最优方案
    • 代码

    #include 
    
    using namespace std;
    
    int main() {
        int m;
        cin>>m;
        cout<<m<<'\n';
        for(int i=1;i<=m;i++) cout<<1<<' ';
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    C.阿宁吃粽子

    • 题意

      • n条带美味值粽子,总的美味值计算如下,安排n个粽子吃的顺序,使得总美味值最大
        W = ∑ k = 1 n a k × 2 k % 10 , k 为吃的次序 W=\sum_{k=1}^{n}a_k\times2^{k\%10},k为吃的次序 W=k=1nak×2k%10,k为吃的次序

      • 如果有多种符合要求的解,那么把美味值大的放到后面

    • 题解

      • 构造,按要求构造一个最大的排序。先把美味值排序,美味值越大的放在2次幂权值大的位置上,可以用二维vector记录权值k时有哪些位置,然后一次把排好序的粽子排放在位置上
      • 对于我来说,难点在代码实现上
    • 代码

    #include 
    #include 
    #include 
    
    using namespace std;
    const int N=2e5+10;
    
    int n,a[N],ans[N];//记录美味值,记录答案
    vector<int> b[12];//记录权值为0~9的位置有哪些
    
    int main() {
        cin>>n;
        for(int i=1;i<=n;i++) {
            cin>>a[i];
            b[i%10].push_back(i);//初始化好对应权值的位置
        }
        sort(a+1,a+1+n);//排序
        
        for(int i=n;i;i--) {//贪心把美味值大的放在权值大的位置
            for(int j=9;j>=0;j--) {
                if(b[j].size()) {
                    int x=b[j].back();//从大的位置开始放,满足题目要求
                    b[j].pop_back();
                    ans[x]=a[i];//每填一个就break去填下一个
                    break;
                }
            }
        }
        
        for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
        puts("");
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    D.阿宁的质数

    • 题意

      • 询问q次,长度为n的数组中前x个数中没有出现的最小质数
    • 题解

      • 由题得,当a为n个从小到大的质数,那么对于任意一个询问,暴力寻找答案时,寻找复杂度最高。因为一旦a有不连续的质数,那么暴力寻找时就不需要从1到x,在x之前就找到没有出现的最小质数了。因此预处理出前2e5个质数就是极限的寻找范围了,同时应该用线性筛1~3e6左右个数才能筛出2e5个素数
      • 因为对于所有的位置的答案都是确定的,所以可以先预处理出每个位置的答案。因为查找的范围是一个从1开始的不断向后延展的区间,切寻找的是最小没出现的质数,所以可以利用双指针思维,指向答案的指针随着区间扩展时单调(不严格)递增的。
    • 代码

    #include 
    
    using namespace std;
    const int N=2e5+10,M=3e6+10;//数组的大小,筛素数的范围
    
    int n,q,a[N],ans[N];//存每个位置的答案
    
    int cnt,primes[M];//筛素数
    bool st[M];
    
    bool vis[M];//找答案的辅助数组
    
    void get_primes() {//线性筛素数
        for(int i=2;i<M;i++) {
            if(!st[i]) primes[cnt++]=i;
            for(int j=0;primes[j]<=M/i;j++) {
                st[primes[j]*i]=true;
                if(i%primes[j]==0) break;
            }
        }
    }
    
    int main() {
        get_primes();
        //cout<
        
        cin>>n>>q;
        for(int i=1;i<=n;i++) cin>>a[i];
        
        int p=0;//指向答案的指针
        for(int i=1;i<=n;i++) {//遍历每个位置找答案
            if(a[i]<M) vis[a[i]]=1;//如果这个数在查找范围内,标记已经出现过
            while(vis[primes[p]]) p++;//从前往后单调寻找第一个没有出现的质数
            ans[i]=primes[p];//答案
        }
        
        while(q--) {
            int x; cin>>x;
            cout<<ans[x]<<'\n';
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    E.阿宁睡大觉

    • 题意

      • 给定一个只含有’Z’和’z’的字符串,可以进行删除操作,每次删除一个字符,最多删除k次

      • 求下式的最大值
        ∑ i = 1 l e n ( s ) − 1 w ( s i ) × w ( s i + 1 ) 其中 w ( Z ) = 2 , w ( z ) = 0 \sum_{i=1}^{len(s)-1}w(s_i)\times w(s_{i+1})\\ 其中w(Z)=2,w(z)=0 i=1len(s)1w(si)×w(si+1)其中w(Z)=2,w(z)=0

    • 题解

      • 由于只有’ZZ’的情况才能给答案做贡献,所以可以统计连续Z的子段来统计没有进行删除时的答案
      • 再统计所有z的连续子段及其长度(非开头和结尾,因为只要z在开头或者结尾删不删除对答案没有影响),从小到大排序去贪心删除这些子段,每删除一个子段答案多了一个ZZ的答案贡献
    • 代码

    #include 
    #include 
    #include 
    
    using namespace std;
    const int N=2e5+10;
    
    int n,k,ans;
    char s[N];
    vector<int> sub;//存储z子段的长度
    
    int main() {
        cin>>n>>k;
        cin>>s+1;
        for(int i=1;i<=n;i++) {
            int p=i;
            while(s[p]==s[i] && p<=n) p++;
            p--;
            if(s[i]=='Z') ans+=(p-i);//连续的Z子段对答案的贡献
            else if(i!=1 && p!=n) sub.push_back(p-i+1);//非两端的z子段记录
            i=p;
        }
        
        sort(sub.begin(),sub.end());//排序后,贪心删除zz子段
        for(auto x:sub) 
            if(x<=k) {k-=x; ans++;}
        cout<<ans*4<<'\n';//每个ZZ的分数为4
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    F.阿宁去游玩

    • 题意

      • 给定一个含n个节点的无向图,每个节点有0,1两种性质,如果性质相同那么边权为x,否则为y
      • 可以通过魔法将除了所在点的其他点都变换性质,花费边权z
      • 问从1到n的最短路为多少
    • 题解

      • 正权最短路可以直接用spfa
      • 建图,边权有两种情况,不用魔法直接是x(y),使用魔法为y+z(x+z),选其中边权小的即可。注意,相邻的点相对性质不变,所以不需要考虑全局怎么变化的
    • 代码

    #include 
    #include 
    
    using namespace std;
    const int N=2e5+10;
    typedef long long LL;
    const LL INF=1e18+10;//注意数据范围
    
    int n,m,x,y,z,a[N];//数组为每个节点的性质
    int h[N],e[2*N],w[2*N],ne[2*N],idx;//无向图
    bool st[N];//最短路
    LL dis[N];
    
    void add(int a,int b,int c) {//加一条权值为c的边
        e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
    }
    
    int main() {
        cin.tie(0)->sync_with_stdio(false);
        
        cin>>n>>m>>x>>y>>z;
        for(int i=1;i<=n;i++) cin>>a[i],h[i]=-1,dis[i]=INF;//初始化
        while(m--) {//建图
            int u,v;
            cin>>u>>v;
            if(a[u]==a[v]) {
                add(u,v,min(x,y+z));
                add(v,u,min(x,y+z));
            }
            else {
                add(u,v,min(y,x+z));
                add(v,u,min(y,x+z));
            }
        }
        
      //spfa最短路
        dis[1]=0;
        queue<int> q;
        q.push(1); st[1]=1;
        while(q.size()) {
            int t=q.front();q.pop(); st[t]=0;
            
            for(int i=h[t];~i;i=ne[i]) {
                int j=e[i];
                if(dis[j]>dis[t]+w[i]) {//注意是dis[t]和w[i]
                    dis[j]=dis[t]+w[i];
                    if(!st[j]) q.push(j),st[j]=1;
                }
            }
        }
        
        cout<<dis[n]<<'\n';//输出最短路答案
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
  • 相关阅读:
    Docker
    在不同的系统下解决apache2和nginx伪静态问题(非宝塔页面)wordpress通用
    BuyVM 挂载存储块
    C++ 函数模板
    从Endnote导入Zotero(含PDF)
    shell变量
    数据库:Hive转Presto(四)
    Word中Endnote加载项不见了怎么处理?
    助推科技强国高质量发展《科创超级训练营》系列活动正式拉开帷幕
    2023 恒创海外服务器双11优惠汇总【附开通流程】
  • 原文地址:https://blog.csdn.net/m0_49843646/article/details/126766367