• 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;
    }
    
  • 相关阅读:
    yzoj P2344 斯卡布罗集市 题解
    yzoj P2350 逃离洞穴 题解
    yzoj P2349 取数 题解
    JXOI 2017 颜色 题解
    NOIP 2009 最优贸易 题解
    CH 4302 Interval GCD 题解
    CH4301 Can you answer on these queries III 题解
    Luogu2533[AHOI2012]信号塔
    Luogu3320[SDOI2015]寻宝游戏
    Luogu3187[HNOI2007]最小矩形覆盖
  • 原文地址:https://www.cnblogs.com/charles1999/p/12683617.html
Copyright © 2020-2023  润新知