【NOIP模拟】 20151006模拟

8 篇文章 0 订阅
7 篇文章 0 订阅

题目

这里看题目,密码: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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值