zoukankan      html  css  js  c++  java
  • 2017西电第一次省赛选拔赛补题

    https://vjudge.net/contest/161101#overview


    A.判断B是否能整除A的每一个素因子。

    #include<bits/stdc++.h>
    using namespace std;
    
    int prime[1000005],vis[1000005] = {0};
    long long a,b;
    
    int main()
    {
        ios::sync_with_stdio(false);
        int T,z = 0;
        cin >> T;
        int cnt = 0;
        for(int i = 2;i <= 1000000;i++)
        {
            if(!vis[i]) prime[++cnt] = i;
            for(int j = 1;i*prime[j] <= 1000000 && j <= cnt;j++)
            {
                vis[prime[j]*i] = 1;
                if(i%prime[j] == 0) break;
            }
        }
        while(T--)
        {
            cin >> a >> b;
            cout << "Case #" << ++z << ": ";
            int flag = 0;
            for(int i = 1;(long long)prime[i]*prime[i] <= a;i++)
            {
                if(a%prime[i] == 0)
                {
                    while(a%prime[i] == 0)  a /= prime[i];
                    if(b%prime[i]) flag = 1;
                }
            }
            if(b%a) flag = 1;
            if(flag)    cout << "NO" << endl;
            else    cout << "YES" << endl;
        }
        return 0;
    }
    View Code

    B.显然,最优解是每次选择一个人就把他HP耗尽。假设只有两个人,则

    先攻击第一个人消耗:DPS1HP1+DPS2(HP1+HP2)

    先攻击第二个人消耗:DPS2HP2+DPS1(HP1+HP2)

    可以得出当DPS1/HP1 > DPS2/HP2时,攻击第一个人消耗小。

    由此推广到n个人的情况,按DPSi/HPi排序即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    struct xx
    {
        int hp,dps;
        friend bool operator <(xx a,xx b)
        {
            return a.dps*b.hp > a.hp*b.dps;
        }
    }a[25];
    
    int main()
    {
        ios::sync_with_stdio(false);
        while(cin >> n)
        {
            for(int i = 1;i <= n;i++)   cin >> a[i].dps >> a[i].hp;
            sort(a+1,a+1+n);
            int ans = 0,sum = 0;
            for(int i = 1;i <= n;i++)
            {
                sum += a[i].hp;
                ans += sum*a[i].dps;
            }
            cout << ans << endl;
        }
        return 0;
    }
    View Code

    C.先把前一半的密文翻译乘明码,KMP求后半的在前半的最长前缀。

    #include<bits/stdc++.h>
    using namespace std;
    
    string s,ss;
    int nextt[200005];
    map<char,char> mp;
    
    void get_next(string s)
    {
        int len = s.length();
        int i = 0,j = -1;
        nextt[0] = -1;
        while(i < len)
        {
            if(j == -1 || s[i] == s[j]) nextt[++i] = ++j;
            else    j = nextt[j];
        }
    }
    
    int main()
    {
        int T;
        cin >> T;
        while(T--)
        {
            cin >> ss >> s;
            for(int i = 0;i < ss.length();i++)  mp[ss[i]] = i+'a';
            int len = s.length(),endd = (len+1)/2;
            string sss = s;
            for(int i = 0;i < endd;i++) s[i] = mp[s[i]];
            s.insert(endd,1,'+');
            get_next(s);
            int cnt = len-nextt[len+1];
            for(int i = 0;i < cnt;i++)  cout << sss[i];
            for(int i = 0;i < cnt;i++)  cout << mp[sss[i]];
            cout << endl;
        }
        return 0;
    }
    View Code

    D.set模拟,注意连续在一个点吃的时候,方向不改变。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m,cnt[100005];
    set<int> s;
    set<int>::iterator it;
    
    int main()
    {
        ios::sync_with_stdio(false);
        int T,z = 0;
        cin >> T;
        while(T--)
        {
            s.clear();
            memset(cnt,0,sizeof(cnt));
            cin >> n >> m;
            int dir = 2,now = 0;
            long long ans = 0;
            while(m--)
            {
                int a,b;
                cin >> a;
                if(a == 0)
                {
                    cin >> b;
                    if(cnt[b] == 0) s.insert(b);
                    cnt[b]++;
                }
                else
                {
                    if(s.size() == 0)   continue;
                    it = s.lower_bound(now);
                    int x = 1e9,y = 1e9;
                    if(it != s.end())   y = *it-now;
                    if(it != s.begin())
                    {
                        it--;
                        x = now-*it;
                        it++;
                    }
                    if(it != s.end() && now == *it);
                    else if(x < y || x == y && dir == 1)
                    {
                        it--;
                        ans += x;
                        dir = 1;
                    }
                    else
                    {
                        ans += y;
                        dir = 2;
                    }
                    now = *it;
                    cnt[*it]--;
                    if(cnt[*it] == 0)   s.erase(it);
                }
            }
            cout << "Case " << ++z << ": " << ans << endl;
        }
    }
    View Code

    E.因为每两个点之间有且只有一条单向边,拓扑排序判断是否存在环即可,有环肯定有三元环。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,in[2005];
    string s;
    vector<int> v[2005];
    
    bool topsort()
    {
        int cnt = 0;
        while(cnt < n)
        {
            int t;
            for(t = 1;t <= n;t++)
            {
                if(in[t] == 0)  break;
            }
            if(t == n+1)    return 1;
            in[t]--;
            cnt++;
            for(int i = 0;i < v[t].size();i++)
            {
                in[v[t][i]]--;
            }
        }
        return 0;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        int T,z = 0;
        cin >> T;
        while(T--)
        {
            cin >> n;
            for(int i = 1;i <= n;i++)   v[i].clear();
            memset(in,0,sizeof(in));
            for(int i = 1;i <= n;i++)
            {
                cin >> s;
                s = " "+s;
                for(int j = 1;j < s.length();j++)
                {
                    if(s[j] == '1') in[j]++;
                    v[i].push_back(j);
                }
            }
            cout << "Case #" << ++z << ": ";
            if(topsort())   cout << "Yes" << endl;
            else    cout << "No" << endl;
        }
        return 0;
    }
    View Code

    F.逆序建树就可以了。

    #include<iostream>
    using namespace std;
    
    struct xx
    {
        xx *l,*r;
        char x;
    }*root;
    string s[10005];
    
    void insertt(xx *&p,char x)
    {
        if(p == NULL)
        {
            p = new xx;
            p->l = NULL;
            p->r = NULL;
            p->x = x;
            return;
        }
        if(p->x > x)    insertt(p->l,x);
        else    insertt(p->r,x);
    }
    
    void printff(xx *p)
    {
        if(!p)  return;
        cout << p->x;
        printff(p->l);
        printff(p->r);
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        while(1)
        {
            int n = 0;
            while(cin >> s[++n] && s[n] != "*" && s[n] != "$");
            root = NULL;
            for(int i = n-1;i >= 1;i--)
            {
                for(int j = 0;j < s[i].length();j++)    insertt(root,s[i][j]);
            }
            printff(root);
            cout << endl;
            if(s[n] == "$") break;
        }
        return 0;
    }
    View Code

    G.Bretschneider公式

    #include<bits/stdc++.h>
    using namespace std;
    
    int a,b,c,d;
    
    int main()
    {
        ios::sync_with_stdio(false);
        int T,z = 0;
        cin >> T;
        while(T--)
        {
            cin >> a >> b >> c >> d;
            if(a+b+c <= d || a+c+d <= b || a+b+d <= c || b+c+d <= a)
            {
                cout << "Case " << ++z << ": -1" << endl;
                continue;
            }
            double t = (double)(a+b+c+d)/2;
            double ans = sqrt((t-a)*(t-b)*(t-c)*(t-d));
            cout << "Case " << ++z << ": " << fixed << setprecision(6) << ans << endl;
        }
        return 0;
    }
    View Code

    H.找规律打个表。

    #include<bits/stdc++.h>
    using namespace std;
    
    long long n,a[50000];
    
    int main()
    {
        ios::sync_with_stdio(false);
        for(int i = 1;i <= 50000;i++) a[i] = (long long)i*(i-1);
        int T;
        cin >> T;
        while(T--)
        {
            cin >> n;
            int t = lower_bound(a+1,a+50000,n)-a-1;
            long long ans1 = (long long)t*t+n-a[t];
            long long ans2 = 0,now = 1;
            while(now*now < ans1)   ans2 += (now*now-(now-1)*(now-1))*(now-1),now++;
            ans2 += (ans1-(now-1)*(now-1)+1)*(now-1);
            cout << ans1 << " " << ans2 << endl;
        }
        return 0;
    }
    View Code

    I.直接模拟加法。

    #include<bits/stdc++.h>
    using namespace std;
    
    string s;
    int a[100005];
    
    int main()
    {
        ios::sync_with_stdio(false);
        int T;
        cin >> T;
        while(T--)
        {
            memset(a,0,sizeof(a));
            cin >> s;
            int sum = 0,cnt = 0;
            for(int i = s.length()-1;i >= 0;i--)
            {
                a[++cnt] = s[i]-'0';
                sum += a[cnt];
            }
            sum %= 10;
            do
            {
                if(a[1] != 9)
                {
                    a[1]++;
                    sum = (sum+1)%10;
                }
                else
                {
                    int t = 1;
                    a[1] = 0;
                    sum = 0;
                    for(int i = 2;i <= cnt;i++)
                    {
                        if(t)
                        {
                            a[i]++;
                            if(a[i] == 10)  a[i] = 0;
                            else    t = 0;
                        }
                        sum += a[i];
                    }
                    if(t)
                    {
                        a[++cnt] = 1;
                        sum++;
                    }
                    sum %= 10;
                }
            }while(sum != 0);
            int t = 100004;
            while(a[t] == 0)   t--;
            while(t >= 1)
            {
                cout << a[t];
                t--;
            }
            cout << endl;
        }
        return 0;
    }
    View Code

    J.把所有U替换成I,打表所有可能的个数。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,ok[3000008];
    string s;
    
    int main()
    {
        ios::sync_with_stdio(false);
        int now = 1;
        while(now <= 3000000)
        {
            ok[now] = 1;
            now *= 2;
        }
        for(int i = 3000000;i >= 1;i--)
        {
            if(ok[i+6])   ok[i] = 1;
        }
        int T;
        cin >> T;
        while(T--)
        {
            cin >> s;
            int flag = 0,sum = 0;
            if(s[0] != 'M') flag = 1;
            for(int i = 1;i < s.length();i++)
            {
                if(s[i] == 'M') flag = 1;
                else if(s[i] == 'U')    sum += 3;
                else    sum++;
            }
            if(flag == 0 && ok[sum])    cout << "Yes" << endl;
            else    cout << "No" << endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/zhurb/p/6810809.html
Copyright © 2011-2022 走看看