1. 程式人生 > 其它 >The 14th Jilin Provincial Collegiate Programming Contest

The 14th Jilin Provincial Collegiate Programming Contest

The 14th Jilin Provincial Collegiate Programming Contest

目錄

Problem A. Chord

Problem B. Problem Select

題解

簽到題,sscanf從字串中讀入數字,排個序取前k個。

程式碼

點選檢視程式碼
#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i)
#define per(i, l, r) for (int i = r, iss = l; i >= iss; --i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;

using namespace std;

const int N = 1050;

int main()
{
    int tc;
    int n, m, k, t, in;
    char s[N];
    vector<int> ans;
    for (scanf("%d", &tc); tc; --tc)
    {
        scanf("%d%d", &n, &k);
        rep(i, 1, n)
        {
            scanf("%s", s);
            m = strlen(s);
            rep(i, 0, m - 1) if (s[i] == '/') in = i;
            sscanf(s + in + 1, "%d", &t);
            ans.push_back(t);
        }
        sort(ans.begin(), ans.end());
        rep(i, 0, k - 1) printf(i + 1 == k ? "%d\n" : "%d ", ans[i]);
        ans.clear();
    }

    return 0;
}
/*
2
3 2
http://acm.hit.edu.cn/problemset/1003
http://acm.hit.edu.cn/problemset/1002
http://acm.hit.edu.cn/problemset/1001
4 1
http://acm.hit.edu.cn/problemset/1001
http://acm.hit.edu.cn/problemset/2001
http://acm.hit.edu.cn/problemset/3001
http://acm.hit.edu.cn/problemset/501

*/

Problem C. String Game

題解

求一個串在另一個串中作為子串的出現次數

a[1:n] 為母串, b[1:m] 為子串;
f[i][j] = k : b[1:j]在a[1:i]中作為子串 且 a[i]=b[j] 出現的次數, 有轉移方程$ f[i][j]= \Sigma_{x=1}^{i-1}{f[x][j-1]}$

程式碼

點選檢視程式碼
#include<bits/stdc++.h>

#define rep(i,l,r) for(int i=l,iss=r;i<=iss;++i)
#define per(i,l,r) for(int i=r,iss=l;i>=iss;--i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;

using namespace std;

const int N=5050,M=1050,P=1e9+7;

int n,m;
char a[N],b[M];
ll f[N];

int main ()
{
    while(scanf("%s%s",a+1,b+1)!=EOF)
    {
        n=strlen(a+1),m=strlen(b+1);
        rep(i,1,n)f[i]=(a[i]==b[1]?1:0);
        rep(j,2,m)
        {
            ll prefix_sum=0;
            rep(i,1,n)prefix_sum+=f[i];
            per(i,1,n)
            {
                prefix_sum-=f[i];
                if(a[i]==b[j])f[i]=prefix_sum%P;
                else f[i]=0;
            }
        }
        ll ans=0;
        rep(i,1,n)ans+=f[i];
        printf("%lld\n",ans%P);

    }

    return 0;
}

/*
eeettt
et
eeettt
te
*/

Problem D. Trie

Problem E. Shorten the Array

題解

結論題

什麼情況下會是1?: \(\exist s[i],s.t.\ s[i]\ \%\ min_x{s[x]}!=0\)
其它情況: \(ans=cnt(min_x{s[x]})+1>>1\)

程式碼

點選檢視程式碼
#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i)
#define per(i, l, r) for (int i = r, iss = l; i >= iss; --i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;

using namespace std;

const int N = 1e6 + 500;

int n, a[N];

int main()
{
    int tc, ele, cnt;
    bool flag;
    for (scanf("%d", &tc); tc; --tc)
    {
        scanf("%d", &n);
        rep(i, 1, n) scanf("%d", a + i);
        ele = a[1], flag = false;
        rep(i, 1, n) if (a[i] < ele) ele = a[i];
        rep(i, 1, n) if (a[i] % ele != 0)
        {
            flag = true;
            break;
        }
        if (flag)
        {
            printf("1\n");
        }
        else
        {
            cnt = 0;
            rep(i, 1, n) if (a[i] == ele) cnt++;
            printf("%d\n", cnt + 1 >> 1);
        }
    }

    return 0;
}

Problem F. Queue

題解

可以是一道較難的題目, 動態逆序對可持久化線段樹可做, 出題人仁慈地放過了暴力;

考察交換兩個數字對逆序對數量的貢獻, 僅有 \(p_1<i<p_2, s[i] \in \left[s[p_1],s[p_2]\right]\) 中的元素會產生貢獻;

程式碼

點選檢視程式碼
#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, iss = r; i <= iss; ++i)
#define per(i, l, r) for (int i = r, iss = l; i >= iss; --i)
#define pb emplace_back
#define endl '\n'
typedef long long ll;

using namespace std;

const int N = 1e5 + 500;

int n, s[N], m;
ll ori, ans;

struct BIT
{
#define Low_Bit(x) (x & (-x))

private:
    int ran, bit[N];

public:
    BIT(int ran) : ran(ran)
    {
        memset(bit, 0, sizeof(bit));
    }
    void add(int p, int x)
    {
        for (; p <= ran; p += Low_Bit(p))
            bit[p] += x;
    }
    int sum(int p)
    {
        int rec = 0;
        for (; p > 0; p -= Low_Bit(p))
            rec += bit[p];
        return rec;
    }

#undef Low_Bit
};

void Init();
void Get_inversions();
void Process();

int main()
{
    int tc;
    for (scanf("%d", &tc); tc; --tc)
    {
        Init();
        Get_inversions();
        Process();
        printf("%lld\n", ans);
    }

    return 0;
}

void Process()
{
    scanf("%d", &m);
    int l, r,f,lv,rv, cnt;
    rep(i,1,m)
    {
        scanf("%d%d", &l, &r);
        if (s[l] == s[r])
            continue;

        cnt = 1;
        if (s[l] < s[r])f=1,lv=s[l],rv=s[r];
        else f=-1,lv=s[r],rv=s[l];

        rep(j,l+1,r-1)
        {
            if (s[j] >= lv && s[j] <= rv)cnt++;
            if (s[j] >  lv && s[j] <  rv)cnt++;
        }

        ori=ori+f*cnt;

        if(ori<ans)ans=ori;
        swap(s[l], s[r]);
    }
}

void Init()
{
    n = m = 0;
    ori = ans = 0ll;
    memset(s, 0, sizeof(s));
    return;
}

void Get_inversions()
{
    scanf("%d", &n);
    rep(i, 1, n) scanf("%d", s + i);
    rep(i, 1, n)++ s[i];

    int max_s = s[1];
    rep(i, 1, n) if (s[i] > max_s) max_s = s[i];

    BIT *bit = new BIT(max_s);
    per(i, 1, n)
    {
        ori += bit->sum(s[i] - 1);
        bit->add(s[i], 1);
    }
    ans = ori;

    delete bit;
}

Problem G. Matrix

題解

當橫縱座標的乘積為奇數時, $ a(i,j)=1 $ ;
即橫縱座標值應分別為奇數;
$ans= \left\lfloor \sqrt{n} \right\rfloor* \left\lfloor \sqrt{m} \right\rfloor $

Problem H. Curious

題解

莫比烏斯反演 unfinished

Problem I. World Tree

Problem J. Situation

Problem K. Forager

Problem L. Swimmer

Problem M. Upanishad

Problem N. Expressway