1. 程式人生 > 實用技巧 >浙江省程式設計競賽2019

浙江省程式設計競賽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\n", ans); } // cout <<get_divisors(100000).size() <<endl; }
View Code

EZOJ - 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;
    }
}