zoukankan      html  css  js  c++  java
  • 浙江省程序设计竞赛2019

    B - Element Swapping

     ZOJ - 4101 

    题意:

    题解

    可以求得a[i] + a[j] = d2/d1

    #include <iostream>
    #include <string>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <assert.h>
    #include <map>
    #include <set>
    #include <bitset>
    #include <iomanip>
    #include <stack>
    #include <deque>
    #include <unordered_map>
    #include <cmath>
    using namespace std;
    #define STDIN                      
        freopen("in.txt", "r", stdin); 
        freopen("out.txt", "w", stdout);
    
    #define int long long
    inline int read(){char tempt = getchar();int x = 0, f = 0;while (tempt < '0' || tempt > '9')f |= tempt == '-', tempt = getchar();while (tempt >= '0' && tempt <= '9')x = x * 10 + tempt - '0', tempt = getchar();return f ? -x : x;}
    int n, x, y;
    const int N = 1e5 + 10;
    int a[N];
    int num[N];
    vector<int> get_divisors(int x)
    {
        vector<int> res;
        for (int i = 1; i <= min(x / i, n); i ++ )
            if (x % i == 0)
            {
                res.push_back(i);
                if (i != x / i &&((x/i)<=n)) res.push_back(x / i);
            }
        sort(res.begin(), res.end());
        return res;
    }
    signed main()
    {
        //STDIN
        int t;
        cin >> t;
        for (int _ = 1; _ <= t; _++)
        {
            
            n = read(), x = read(), y = read();
            memset(num, 0, sizeof num);
            for (int i = 0; i < n; i++)
            {
                // scanf("%lld", &a[i]);
                a[i] = read();
                num[a[i]]++;
            }
            int sum1 = 0;
            int sum2 = 0;
            for (int i = 0; i < n; i++)
            {
                sum1 += (i+1)*a[i];
            }
            for (int i = 0; i < n; i++)
            {
                sum2 += (i+1)*a[i]*a[i];
            }
            int d1 = sum1-x;
            int d2 = sum2-y;
            // cout << d1 << " " << d2 << endl;
            if (d1 == 0 && d2 == 0)
            {
                int cnt = 0;
                map<int,int> ma;
                for (int i = 0;  i< n; i++)
                {
                    if (ma.count(a[i]) >= 1) cnt += ma[a[i]];
                    ma[a[i]]++;
                }
                cout << cnt << endl;
                continue;
            }
            if (d1 == 0 || d2 == 0)
            {
                cout << 0 << endl;
                continue;
            }
            if (d2%d1!=0){
                cout << 0 << endl;
                continue;
            }
            int xx = d2/d1;
            // cout << xx << endl;
            if (xx <= 0) 
            {
                cout << 0 << endl;
                continue;
            }
            map<int, set<int> > ma;
            int ans = 0;
            vector<int> tmp = get_divisors(d1);
            for (int i = 0; i < n; i++)
            {
                // int d = xx-a[i];
                // if (a[i] == d) continue;
                // if (ma.count(d) >=1 && d1%(a[i] - d) == 0 &&(d2%(a[i]*a[i]-d*d) == 0))
                // {
                //     // d1%(i-j)
                //     auto &se = ma[d];
                //     for (auto &p:tmp)
                //     {
                //         // if (i-p > i-1)
                //         if (p >= i) break;
                //         if (se.find(i-p) != se.end() && (d2%p == 0)) ans++;
                //     }
                    
                // }
                // ma[a[i]].insert(i);
                int aj = xx - a[i];
                int s = aj - a[i];
                if (s!= 0 && aj > 0 && d1%s == 0)
                {
                    int cnt = (d1)/s;
                    cnt += i;
                    if (cnt <= n && cnt > i && a[cnt] ==aj) ans++;
                }
            }
            printf("%lld
    ", ans);
        }
        // cout <<get_divisors(100000).size() <<endl;
    
    }
    View Code

    ZOJ - 4104

    题意:

    一个数列,每次操作可以将任意一个数提至数列最前端,问至少操作几次可以将数列变为非降数列?

    题解:

    可以观察到,任何数列,都可以通过最多n-1次操作变成非降数列,我们在建一个与原来数组一样的数组,从后往前考虑,如果这个数的位置正确,则跳过,如果不正确,那么这个数肯定要往前提至少一次,那么对于这个数前面的数,他们都会往后移一个

    我们定义一个变量记录移动次数,cnt,那么当我们处理下一个数时,他的位置已经往后移了cnt个,那么让他与a[i+cnt]比较,如果相等,则跳过,如果不相等,说明在这个数之前操作的数,需要在往前移,那么cnt++。这样处理完cnt就是最后的答案。

    const int N = 1e5 + 10;
    int num[N];
    signed main()
    {
        // STDIN
        int t;
        cin >> t;
        for (int _ = 1; _ <= t; _++)
        {
            int n;
            cin >> n;
            vector<int> a(n), b(n);
            for (int i = 0; i < n; i++)
            {
                scanf("%d",&a[i]);
                b[i] = a[i];
            }
            sort(a.begin(), a.end());
            int cnt = 0;
            for (int i = n-1; i>= 0; i--)
            {
                if (a[(i+cnt)] != b[i])
                {
                    cnt++;
                }
            }
            cout <<cnt << endl;
        }
    }

    F - Abbreviation

     ZOJ - 4105 

    题意:

    将字符串的元音字母删掉,注意第一个字母不删,输出处理后的字母

    题解:水题

    G - Lucky 7 in the Pocket

     ZOJ - 4106

    水题

    H - Singing Everywhere

     ZOJ - 4107

    题意:

    一个数列,如果a[i]>a[i-1] && a[i]>a[i+1],这样算一次破音,问当最多可以删掉一个数时,让破音数最少,最少的破音数是多少?

    题解

    暴力判断删掉每一个数删掉后的破音数,注意边界的处理

    #define int long long
    
    set<int> se;
    signed main()
    {
        //STDIN
        int t; cin >> t;
        for (int _ = 1; _ <= t; _++)
        {
            int n;
            cin >> n;
            vector<int> a;
            for (int i = 1; i <= n; i++)
            {
                int x;
                scanf("%lld", &x);
                a.push_back(x);
            }
            for (int i = 1; i < n-1; i++)
            {
                if (a[i] > a[i-1] && a[i] > a[i+1]) se.insert(i);
            }
            int ans = se.size();
            int res = ans;
            for (int i = 0; i < n; i++)
            {
                if (i == 0)
                {
                    if (se.find(1) != se.end())
                    {
                        res = min(ans-1, res);
                    }
                }
                else if (i == n-1)
                {
                    if (se.find(n-2) != se.end())
                    {
                        res = min(ans-1, res);
                    }
                }
    
                else{
                    int t = ans;
                    if (se.find(i) != se.end()) t--;
                    if ( i-2 >=0)
                    {
                        if ( a[i-1] > a[i-2] && a[i-1] > a[i+1])
                        {
                            if (se.find(i-1) == se.end()) t++;  
                        }
                        else {
                            if (se.find(i-1) != se.end()) t--;
                        }
                        
                    }
                    if (i+2 <= n-1 )
                    {
                        if(a[i+1] > a[i-1] && a[i+1] > a[i+2])
                        {
                            if (se.find(i+1) == se.end()) t++;
                        }
                        else{
                            if (se.find(i+1) != se.end()) t--;
                        }
                        
                    }
                    res = min(t, res);
                }
            }
            cout << res << endl;
            se.clear();
        }
    }

    I - Fibonacci in the Pocket

     ZOJ - 4108 

    题意:

    求斐波那契数列的区间和是奇数还是偶数

    题解:

    找规律

    int mod1(string a, int b) //高精度a除以单精度b
    {
        int d = 0ll;
        for (int i = 0; i < a.size(); i++)  d = (d * 10 + (a[i] - '0')) % b;  //求出余数
        return d;
    }
    signed main()
    {
       // STDIN
        int t;
        cin >> t;
        for (int _ = 1; _ <= t; _++)
        {
            string a, b;
            cin >> a >> b;
            int a1 = mod1(a,3);
            int b1 = mod1(b,3);
            if ((a1 == 1 && b1 == 2) ||(a1 == 0 && b1 == 0)||(a1 == 1 &&b1 == 0)|| (a1 == 2 && b1 == 1) ||(a1 == 0 && b1 == 2))
            {
                cout<< 0 << endl;
            } 
            else cout << 1 << endl;
        }
    }

     J - Welcome Party

     ZOJ - 4109 

    题意:
    一群人走进一个房间,告诉你每个人之间是朋友的关系,这群人一个一个的走进房间,弱国房间内已经有了自己的朋友,则这个人会高兴,如果房间内没有自己的朋友,这个人就会不高兴

    问怎样排队进入,使不高兴的人最少,并且字典序最小

    题解:

    建图,每一个连通块可以只有一个人不高兴,设立一个虚电,连接所有连通块的最先进入房间的那个人(选取编号最小的节点)然后根据编号用优先队列,从虚点开始bfs搜索

    int n, m, t;
    const int N = 2e6 + 10;
    int h[N], e[N], w[N], ne[N], idx;
    bool st[N];
    int fa[N];
    // vector<int> ans;
    void add(int a, int b)
    {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
        return;
    }
    void init()
    {
        idx = 0;
        
        for (int i = 0; i <= n; i++)
        {
            fa[i] = i;
            st[i] = false;
        }
    
        // ans.clear();
        return;
    }
    int find(int x)
    {
        if (fa[x] == x) return x;
        else return fa[x] = find(fa[x]);
    }
    void unite(int x, int y)
    {
        int fx = find(x), fy = find(y);
        if (fx < fy) fa[fy] = fx;
        else fa[fx] = fy;
        return ;
    }
    
    void bfs()
    {
        priority_queue<int, vector<int>, greater<int> > heap;
        heap.push(0);
        for (int i = 0; i <= n; i++) st[i] = false;
        st[0] = true;
        int cnt = 0;
        while (heap.size())
        {
            auto t = heap.top();
            // ans.push_back(t);
            cnt++;
            if (cnt >1)
            printf("%d%c", t, " 
    "[cnt == n+1]);
            heap.pop();
            for (int i = h[t]; i!= -1; i = ne[i])
            {
                int j = e[i];
                if (st[j]) continue;
                heap.push(j);
                st[j] = true;
            }
        }
        return;
    }
    signed main()
    {
        STDIN
        memset(h, -1, sizeof h);
        scanf("%d", &t);
        for (int _ = 1; _ <= t; _++)
        {
            scanf("%d%d", &n, &m);
            init();
            for (int i = 1; i <= m; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                add(a, b), add(b, a);
                if (find(a) != find(b))
                {
                    unite(a, b);
                }
            }
            int cnt = 0;
            for (int i = 1; i<= n; i++)
            {
    
                if (fa[i] == i)
                {
                    cnt++;
                    add(0, fa[i]);
                }
            }
            printf("%d
    ", cnt);
            bfs();
            for (int i = 0; i <= idx +100; i++) h[i] = -1; 
        }
    }
    View Code
  • 相关阅读:
    qt env
    如何通过迅雷加速下载Android SDK
    Linux下USB从设备使用gadget API
    一些链接
    SMT
    usb topology分析
    Linux驱动的地址空间和硬件地址空间说明
    PCB设计基础知识
    ARM的位置无关程序设计在Bootloader中的应用
    Active Directory基础之一
  • 原文地址:https://www.cnblogs.com/hulian425/p/13696004.html
Copyright © 2011-2022 走看看