【NOIP模擬】 20151006模擬

題目

這裏看題目,密碼:ktix
這裏看三道題的題解,密碼:m65h
喪心病狂的你居然想看我們的成績
Johann是蒟蒻,Orz衆神犇

T1 DEC

可以用map哈希,也可以二分

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long

const int N = 300000;
map<int, int> hash;
int a[N];
int n, c;
ll ans;

inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int main() {
    freopen("dec.in", "r", stdin);
    freopen("dec.out", "w", stdout);
    scanf("%d%d", &n, &c);
    rep(i, 1, n) {
        a[i] = read();
        hash[a[i]]++;
    }
    ans = 0;
    int x;
    rep(i, 1, n) {
        x = a[i] + c;
        ans += (ll)(hash[x]);
    }
    printf("%I64d\n", ans);
    return 0;
}

T2 COUNT

對任意n,例如1234.
先考慮n個數中個位上分別是1~9的個數,先來看1230,顯然1230裏個位是1的數有123個,2到9也是123個。
那麼沒統計的數字就是1230,1231,1232,1233,1234這5個,顯然個位是1的又增加5個。
再來看十位:類似的來看1200,則十位是1~9的數各有120個,剩下還有1201~1234,則十位是1~2的個數分別增加10個,十位是3的增加5個.
以此類推

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long

ll cnt[10] = {0};
ll n;

int main() {
    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);

    scanf("%I64d", &n);
    ll p = 1, m = 0, x = n;
    while(x) {
        m++;
        x /= 10ll;
    }
    while(m--) {
        p *= 10ll;
        ll t = (n / p) * p;
        rep(i, 1, 9) cnt[i] += t / 10;
        t = n - t;
        x = t / (p / 10);
        rep(i, 1, x - 1) cnt[i] += p / 10;
        cnt[x] += t - x * (p / 10) + 1;
    }
    ll ans = 0;
    rep(i, 1, 9) ans += cnt[i] * (ll)(i);
    printf("%I64d\n", ans);
    return 0;
}

T3 SWITCH

對於每個狀態,算法只需要枚舉第一行改變哪些燈的狀態,只要第一行的狀態固定了,接下來的狀態改變方法都是唯一的:每一行需要改變狀態的位置都在上一行中不亮的燈的正下面,因爲只有這樣才能使上一行的燈全亮。我們枚舉第一行的狀態改變方法(共25 種),對於每種方法都依次改變下面幾行的狀態使上面一行燈全亮。到最後一行我們需要判斷是否最後一行也恰好全亮,並更新最小步數。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long

const int inf = 1000000000;
int a[10][10], back_up[10][10];
int T;

int main() {
    freopen("switch.in", "r", stdin);
    freopen("switch.out", "w", stdout);

    scanf("%d", &T);
    while(T--) {
        int ans = inf;
        memset(a, 0, sizeof(a));
        rep(i, 1, 5) {
            char ch = '#';
            while(!isdigit(ch)) ch = getchar();
            rep(j, 1, 5) {
                a[i][j] = ch - '0';
                back_up[i][j] = a[i][j];
                ch = getchar();
            }
        }
        rep(sol, 0, 31) {
            int k = sol, cnt = 0, j = 0;
            while(k) {
                j++;
                if (k & 1) {
                    a[1][j] ^= 1;
                    a[0][j] ^= 1;
                    a[2][j] ^= 1;
                    a[1][j - 1] ^= 1;
                    a[1][j + 1] ^= 1;
                    cnt++;
                }
                k >>= 1;
            }
            rep(i, 2, 5) {
                rep(j, 1, 5) {
                    if (a[i - 1][j] == 0) {
                        cnt++;
                        a[i - 1][j] ^= 1;
                        a[i][j] ^= 1;
                        a[i + 1][j] ^= 1;
                        a[i][j - 1] ^= 1;
                        a[i][j + 1] ^= 1;
                    }
                }
            }
            int tag = 1;
            rep(i, 1, 5) 
                if (a[5][i] == 0) {
                    tag = 0; break;
                }
            if (cnt < ans && tag) ans = cnt;
            rep(i, 1, 5) rep(j, 1, 5) a[i][j] = back_up[i][j];
        }
        if (ans <= 6) printf("%d\n", ans);
        else printf("-1\n");
    }
    return 0;
}

T4 ORZ

題面不錯
至於題目內容麼,送到手的n2 DP

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long

const int inf = 1000000000, N = 3000;
int cnt[5], f[N], a[N];
int n, m;

int main() {
    freopen("orz.in", "r", stdin);
    freopen("orz.out", "w", stdout);

    scanf("%d%d", &n, &m);
    rep(i, 1, n) scanf("%d", &a[i]);
    rep(i, 1, n) f[i] = inf;
    rep(i, 1, n) {
        memset(cnt, 0, sizeof(cnt));
        red(j, i, 1) {
            cnt[a[j]]++;
            if (cnt[1] == 0 || cnt[2] == 0 || fabs(cnt[1] - cnt[2]) <= m) {
                f[i] = min(f[j - 1] + 1, f[i]);
            }
        }
    }
    printf("%d\n", f[n]);
    return 0;
}

T5 TREECUT

就是求樹的重心
沒了

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long

const int N = 20000;
struct edge{
    int u, v, nxt;
}e[N];
int head[N], sum[N], fa[N], lis[N];
int n, lim, num, tail = 0;

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
    while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

void addedge(int x, int y) {
    e[++tail].u = x;
    e[tail].v = y;
    e[tail].nxt = head[x];
    head[x] = tail;
}

void BFS(int x) {
    int m = n; fa[x] = -1;
    queue<int> q;
    q.push(x);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        lis[m--] = u;
        for(int i = head[u]; i != -1; i = e[i].nxt) {
            int v = e[i].v;
            if (v != fa[u]) {
                fa[v] = u;
                q.push(v);              
            }
        }
    }
}

int main() {
    freopen("treecut.in", "r", stdin);
    freopen("treecut.out", "w", stdout);

    scanf("%d", &n);
    lim = n / 2; num = 0;
    rep(i, 1, n) head[i] = -1, sum[i] = 1;
    rep(i, 1, n - 1) {
        int x, y;
        scanf("%d%d", &x, &y);
        addedge(x, y);
        addedge(y, x);
    }
    BFS(1);
    rep(i, 1, n) {
        int u = lis[i];
        for(int j = head[u]; j != -1; j = e[j].nxt) {
            if (e[j].v == fa[u]) continue;
            sum[u] += sum[e[j].v];
        }
    }
    rep(i, 1, n) {
        if (n - sum[i] > lim) continue;
        int tag = 1, u = i;
        for(int j = head[u]; j != -1; j = e[j].nxt) {
            int v = e[j].v;
            if (v == fa[u]) continue;
            if (sum[v] > lim) {
                tag = 0;
                break;
            }
        }
        if (tag) { printf("%d\n", i); num++; }
    }
    if (!num) printf("NONE\n");
    return 0;
}

尾聲

於是水題的題解就十分速度的寫完了
居然AK了呢
這套題自己還做過的,當時只做了190,突然發現自己還是有過進步的
聽說要月考?停課是第一生產力
老大的有機化學

End.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章