zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 85 (Rated for Div. 2)【ABCDE】(题解)

    目录

    涵盖知识点:思维、贪心、数学。

    比赛链接:传送门

    A - Level Statistics

    题意: 按照时间顺序给出游戏进行次数和通关次数,判断是否合理。
    题解: 保证相邻区间内和总区间进行次数大于等于通关次数且非递减即可。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            int maxp=0,maxc=0;
            bool flag=true;
            while(n--){
                int p,c;
                cin>>p>>c;
                if(p<maxp||c<maxc||p<c||p-maxp<c-maxc){
                    flag=false;
                }
                maxp=max(p,maxp),maxc=max(c,maxc);
            }
            puts(flag?"YES":"NO");
        }
        return 0;
    }
    

    B - Middle Class

    题意: 规定财富大于等于某个阈值即为有钱人,每次操作可以选取一堆人,让他们每个人的财富变为他们的平均值。
    题解: 从大到小排序后贪心。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    ll a[maxn];
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            ll x;
            cin>>n>>x;
            for(int i=1;i<=n;i++)cin>>a[i];
            sort(a+1,a+n+1);
            reverse(a+1,a+1+n);
            int cnt=0;
            ll sum=0;
            for(int i=1;i<=n;i++){
                sum+=a[i];
                if(sum>=x*i)cnt++;
                else break;
            }
            cout<<cnt<<"
    ";
        }
        return 0;
    }
    

    C - Circle of Monsters

    题意: 有一圈怪兽,每个怪兽有(a_i)点生命值,每射击1次怪兽会掉1点生命值,当怪兽死亡时会对下一个怪兽造成(b_i)点伤害,要想消灭所有怪兽最少需要射击多少次。
    题解: 先把所有血量修到前一个怪死亡后会造成的伤害,然后选一个最少的把怪打死的伤害即可。
    Accept Code: 学到了rotate的用法。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=3e6+10;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    ll a[maxn],b[maxn];
    int main(){
        int t;
        cin>>t;
        while(t--){
            ll n,ans=inf,cnt=0;
            scanf("%lld",&n);
            for(int i=0;i<n;i++)scanf("%lld%lld",&a[i],&b[i]);
            rotate(b,b+n-1,b+n);
            for(int i=0;i<n;i++){
                if(a[i]>b[i])cnt+=a[i]-b[i];
            }
            for(int i=0;i<n;i++){
                ll res=0;
                if(a[i]>b[i])res-=(a[i]-b[i]);
                res+=a[i];
                ans=min(ans,res);
            }
            cout<<cnt+ans<<"
    ";
        }
        return 0;
    }
    

    D - Minimum Euler Cycle

    题意: 给定(n)个顶点的完全有向图。要求求出字典序最小的欧拉回路的某个区间。
    题解: 观察题目中给的(n=3)的样例可以看出(left[ 1,2,1,3 ight] left[ 2,3 ight] left[ 1 ight])
    就是说对(1 sim n)的每一个节点,每次从当前点出发依次走到下一个节点再回来是字典序最小的,但是当前点走到(n)时不能回来,要直接走到下一个节点去,不然就会无路可走。最终才回到1节点
    再观察可以发现对于(1 sim n)节点,每组有(2(n-i))个节点,同时奇数位的节点就是它本身,偶数位为当前组内位置除(2+i)
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            ll n, l, r;
            cin>>n>>l>>r;
            ll limit = 1ll * n * (n - 1) + 1;
            ll sum = 0, id = 1;
            for (ll i = l; i <= r && i < limit; i++){
                while (sum + (n - id) * 2 < i)
                    sum += (n - id) * 2, id++;
                ll d = i - sum;
                printf("%lld ", (d & 1) ? id : d / 2 + id);
            }
            if (r == limit)
                cout<<"1 ";
            cout<<"
    ";
        }
    }
    

    E - Divisor Paths

    题意:
    给定一个正整数(D), 以此建图

    1. 每个节点都是(D)的因子
    2. (x,y(x>y))节点之间有无向边存在的条件是(y)(x)因子且(frac{x}{y})是质数
    3. (x,y)之间若有边,则边权是(x)的因子中不是(y)的因子的个数
      给出(q)组询问,求(u,v)之间的最短路径条数

    题解: 首先可以想到,一个节点(u)向另一个节点(v)转移的过程中总是通过抛出一些因子来进行的,其中(v|u)
    那么uu到vv的最短路径就是(d(u)-d(x_1)+d(x_1)-d(x-2)+ldots+d(x_y)-d(v)=d(u)-d(v)),其中(d(x))(x)的因子个数,因此当一个节点能被令一个节点整除时,两节点间的最短路径就是两节点的因子个数之差。考虑到(u)(v)两者不为倍数关系时,因为节点的转移需要通过抛出一些因子来实现,所以需要找个中间节点(x)使得(u->x)并且(v->x),那么显而易见(x)肯定为(u)(v)的公因子,要使的路径最短就是使得(d(u)-d(x)+d(v)-d(x))最小,那么就是使得(d(x))最大,所以(x=gcd(u,v)),那么最终所求就是(g(u,gcd(u,v))*g(v,gcd(u,v))),其中(g(u,v))(u)(v)两点间最短路径的条数
    因为一个节点(u)向另一个节点(v)转移的过程中总是通过抛出一些因子来进行的,那么条数就是这些中间因子的抛出顺序,那么对于(g(u,v)),其中(v|u),令(x=frac{u}{v}),则(g(u,v)=frac{t!}{p_1!*p_2!...p_n!}),其中(t)(x)中各质因子的幂之和,(p_i)(x)中某个质因子的幂,就是排列组合里重复剔除问题除于它的阶乘
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    map<ll, ll> m;
    
    ll calc(ll x){
        if (m[x])
            return m[x];
        ll res = 0, y = x;
        for (ll i = 2; i * i <= y; i++)
            if (y % i == 0){
                while (y % i == 0)
                    y /= i;
                res = (res + calc(x / i)) % mod;
            }
        if (y > 1)
            res = (res + calc(x / y)) % mod;
        return m[x] = res;
    }
    
    int main(){
        ll d, q;
        cin>>d>>q;
        m[1] = 1;
        while (q--){
            ll u, v;
            cin>>u>>v;
            ll w = __gcd(u, v);
            printf("%lld
    ", calc(u / w) * calc(v / w) % mod);
        }
        return 0;
    }
    
  • 相关阅读:
    find
    Spring 中——————ClassPathResource初学
    Cookie 、Session、Token的学习
    JAVA注解之实现原理
    JAVA注解---2
    JAVA注解————1
    函数式遍程----Function
    java 反射的学习实践2
    Spring AOP 之动态代理源码分析
    正则表达式之Pattern.MULTILINE Pattern.DOTALL
  • 原文地址:https://www.cnblogs.com/charles1999/p/12683617.html
Copyright © 2011-2022 走看看