2016 NOIP提高组复赛解题报告 C++

原文网址:http://blog.csdn.net/yhf_2015/article/details/53453562#t0

DAY1 T1 玩具谜题

题目来源:洛谷 1563
吐槽:

对NOIP出题人“魔法师”英语单词拼错表示(滑稽)。

思路:

模拟操作过程,分类讨论即可。 
时间复杂度: O(n+m)

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
    int dir;
    char name[15];
};
node p[100010];
int n, m;
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d%s", &p[i].dir, p[i].name+1);
    int now = 1;
    for(int i = 1; i <= m; i ++){
        int a, b;
        scanf("%d%d", &a, &b);
        if(p[now].dir == 0){
            if(a == 0) now = ((now - b) % n + n) % n;
            else now = (now + b) % n;
        }else{
            if(a == 0) now = (now + b) % n;
            else now = ((now - b) % n + n) % n;
        }
        if(now == 0) now = n;
    }
    printf("%s", p[now].name+1);
    return 0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 300010;
struct node{
    int begin, end, lca, len;
};
node p[maxn];
int n, m, val[maxn];
int _first[maxn], _next[maxn*2], _to[maxn*2], cnt;
int ins1[maxn], ins2[maxn], del1[maxn], del2[maxn];
int nxt[maxn*4], v[maxn*4], cnt1;
int deep[maxn], up[maxn][20];
int ans[maxn];
int ct1[maxn*2], ct2[maxn*2];
inline void add1(int a, int b, int c){
    nxt[++cnt1] = ins1[a];
    v[ins1[a] = cnt1] = c;
    nxt[++cnt1] = del1[b];
    v[del1[b] = cnt1] = c;
}
inline void add2(int a, int b, int c){
    nxt[++cnt1] = ins2[a];
    v[ins2[a] = cnt1] = c;
    nxt[++cnt1] = del2[b];
    v[del2[b] = cnt1] = c;
}
inline void add(int a, int b){
    _next[++cnt] = _first[a];
    _to[_first[a] = cnt] = b;
}
void dfs(int x){
    for(int i = 1; i <= 18; i ++){
        up[x][i] = up[up[x][i-1]][i-1];
    }
    for(int i = _first[x]; i; i = _next[i]){
        if(_to[i] == up[x][0]) continue;
        up[_to[i]][0] = x, deep[_to[i]] = deep[x]+1;
        dfs(_to[i]);
    }
}
void lca(){
    for(int ii = 1; ii <= m; ii ++){
        int x = p[ii].begin, y = p[ii].end;
        if(deep[x] < deep[y]) swap(x, y);
        if(deep[x] != deep[y])
            for(int i = 18; i >= 0; i --)
                if(deep[up[x][i]] >= deep[y]) x = up[x][i];
        if(x != y){
            for(int i = 18; i >= 0; i --)
                if(up[x][i] != up[y][i]) x = up[x][i], y = up[y][i];
            x = up[x][0];
        }
        p[ii].lca = x;
        p[ii].len = deep[p[ii].begin] - deep[x] + deep[p[ii].end] - deep[x];
    }
}
inline void dfs1(int x){
    ans[x] = - ct1[deep[x]+val[x]] - ct2[deep[x]-val[x]+n];
    for(int i = _first[x]; i; i = _next[i]){
        if(_to[i] == up[x][0]) continue;
        dfs1(_to[i]);
    }
    for(int i = ins1[x]; i; i = nxt[i]) ct1[v[i]] ++;
    for(int i = del1[x]; i; i = nxt[i]) ct1[v[i]] --;
    for(int i = ins2[x]; i; i = nxt[i]) ct2[v[i]+n] ++;
    for(int i = del2[x]; i; i = nxt[i]) ct2[v[i]+n] --;
    ans[x] += ct1[deep[x]+val[x]] + ct2[deep[x]-val[x]+n];
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i ++){
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }
    deep[1] = 1, dfs(1);
    for(int i = 1; i <= n; i ++) scanf("%d", &val[i]);
    for(int i = 1; i <= m; i ++) scanf("%d%d", &p[i].begin, &p[i].end); 
    lca();
    for(int i = 1; i <= m; i ++){
        add1(p[i].begin, up[p[i].lca][0], deep[p[i].begin]);
        add2(p[i].end, p[i].lca, deep[p[i].end]-p[i].len);
    }
    dfs1(1);
    for(int i = 1; i < n; i ++) printf("%d ", ans[i]); printf("%d", ans[n]);
    return 0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90


代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf = 2e9;
int n, m, v, e;
int a1[2010], a2[2010];
double dp[2010][2010][2], dis[310][310], w[2010], ans;
int main(){
    scanf("%d%d%d%d", &n, &m, &v, &e);
    for(int i = 1; i <= n; i ++) scanf("%d", &a1[i]);
    for(int i = 1; i <= n; i ++) scanf("%d", &a2[i]);
    for(int i = 1; i <= n; i ++) scanf("%lf", &w[i]);
    for(int i = 0; i <= v; i ++)
        for(int j = 0; j <= v; j ++)
            if(i == j) dis[i][j] = 0;
            else dis[i][j] = inf;
    for(int i = 1; i <= e; i ++){
        int a, b; double c;
        scanf("%d%d%lf", &a, &b, &c);
        dis[a][b] = min(dis[a][b], c);
        dis[b][a] = min(dis[b][a], c);
    } 
    for(int k = 1; k <= v; k ++)
        for(int i = 1; i <= v; i ++)
            for(int j = 1; j <= v; j ++)
                if(dis[i][j] > dis[i][k]+dis[k][j])
                    dis[i][j] = dis[i][k]+dis[k][j];
    for(int i = 0; i <= n; i ++)
        for(int j = 0; j <= m; j ++)
            dp[i][j][0] = dp[i][j][1] = inf;
    dp[1][0][0] = 0;
    dp[1][1][1] = 0;
    for(int i = 2, up; i <= n; i ++){
        up = min(i, m);
        for(int j = 0; j <= up; j ++){
            dp[i][j][0] = min(dp[i][j][0], dp[i-1][j][0]
                        +dis[a1[i]][a1[i-1]]);
            dp[i][j][0] = min(dp[i][j][0], dp[i-1][j][1]
                        +dis[a1[i]][a2[i-1]]*w[i-1]
                        +dis[a1[i]][a1[i-1]]*(1-w[i-1]));
            if(j-1 >= 0) dp[i][j][1] = min(dp[i][j][1], dp[i-1][j-1][0]
                        +dis[a2[i]][a1[i-1]]*w[i]
                        +dis[a1[i]][a1[i-1]]*(1-w[i]));
            if(j-1 >= 0) dp[i][j][1] = min(dp[i][j][1], dp[i-1][j-1][1]
                        +dis[a2[i]][a2[i-1]]*w[i]*w[i-1]
                        +dis[a2[i]][a1[i-1]]*w[i]*(1-w[i-1])
                        +dis[a1[i]][a2[i-1]]*(1-w[i])*w[i-1]
                        +dis[a1[i]][a1[i-1]]*(1-w[i])*(1-w[i-1]));
        }
    }
    ans = inf;
    for(int i = 0; i <= m; i ++) ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
    printf("%.2lf", ans);
    return 0;
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57


代码:

#include <cstdio>
#include <iostream>
using namespace std;
int T, k;
int sum[2010][2010], val[2010][2010];
int a[10010], b[10010], p1, p2;
int main(){
    scanf("%d%d", &T, &k);
    for(int i = 1; i <= T; i ++){
        scanf("%d%d", &a[i], &b[i]);
        p1 = max(p1, a[i]);
        p2 = max(p2, b[i]);
    }
    for(int i = 0; i <= p1; i ++){
        for(int j = 0; j <= min(p2, i); j ++){
            if(j == 0){val[i][j] = 1;continue;}
            val[i][j] = (val[i-1][j] + val[i-1][j-1]) % k;
            if(val[i][j] == 0) sum[i][j] = 1;
        }
    }
    for(int i = 1; i <= p1; i ++){
        for(int j = 1; j <= p2; j ++){
            sum[i][j] = sum[i-1][j] + sum[i][j-1] + sum[i][j] - sum[i-1][j-1];
        }
    }
    for(int i = 1; i <= T; i ++){
        printf("%d\n", sum[a[i]][b[i]]);
    }
    return 0;
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30


代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
using namespace std;
inline int gt(){  
    char _ch = ' ';  
    int _num = 0, _op = 1, _ok = 0;  
    while(1){
        _ch = getchar();
        if(_ch == '-') _op *= -1;  
        else if(_ch >= '0' && _ch <= '9') _num = _num*10 + _ch - '0', _ok = 1;  
        else if(_ok) return _op * _num; 
    } 
}  
int n, m, q, u, v, t;
int left1;
int len[100010], q1[8000010], q2[8000010];
int out[1000010], cnt;
int main(){
    scanf("%d%d%d%d%d%d", &n, &m, &q, &u, &v, &t);
    for(int i = 1; i <= n; i ++) len[i] = gt();
    sort(len+1, len+1+n);
    int p1 = 1, p2 = 0, p3 = 1, p4 = 0, p5 = n, now = 0;
    for(int i = 1; i <= m; i ++){
        if(p5 >= 1 && len[p5] >= MAX(q1[p1], q2[p3])) now = len[p5--] + left1;
        else if(p1 <= p2 && q1[p1] >= q2[p3]) now = q1[p1++] + left1;
        else if(p3 <= p4) now = q2[p3++] + left1;
        if(i%t == 0) out[++cnt] = now;
        left1 += q;
        int new1 = ((long long)now*(long long)u)/(long long)v;
        int new2 = now - new1;
        q1[++p2] = MAX(new1, new2) - left1;
        q2[++p4] = MIN(new1, new2) - left1;
    }
    for(int i = 1; i <= cnt; i ++) printf("%d ", out[i]);
    printf("\n");
    for(int i = 1, w = 0; i <= n+m; i ++, w = 0){
        if(p5 >= 1 && len[p5] >= MAX(q1[p1], q2[p3])) w = len[p5--] + left1;
        else if(p1 <= p2 && q1[p1] >= q2[p3]) w = q1[p1++] + left1;
        else if(p3 <= p4) w = q2[p3++] + left1;
        if(i%t != 0) continue;
        printf("%d ", w);
    }
    return 0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47



代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 0.000000001;
struct point{
    double x, y;
};
int T, n, m, ans = 1e9;
point p[25];
int num[25][25], dp[300010];
int calc(double a, double b){
    int res = 0, now = 1;
    for(int i = 1; i <= n; i ++, now <<= 1){
        double t = a*p[i].x*p[i].x+b*p[i].y;
        if(abs(a*p[i].x*p[i].x+b*p[i].x-p[i].y) < eps){
            res |= now;
        }
    }
    return res;
}
int bits(int x){
    int res = 0;
    for(int i = 1; i <= n; i ++, x >>= 1) if((x&1) == 0) res ++;
    return res;
}
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++){
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        memset(dp, 63, sizeof(dp));
        memset(num, 0, sizeof(num));
        ans = 1e9;
        for(int i = 1; i <= n; i ++){
            for(int j = i+1; j <= n; j ++){
                if(i == j) continue;
                if(abs(p[i].x-p[j].x) < eps) continue;
                double a = (p[i].y*p[j].x-p[j].y*p[i].x)/(p[i].x*p[i].x*p[j].x-p[j].x*p[j].x*p[i].x);
                if(a >= 0) continue;
                double b = (p[i].y-a*p[i].x*p[i].x)/p[i].x;
                num[i][++num[i][0]] = calc(a,b);
            } 
        }
        int MAX = (1<<n)-1;
        dp[0] = 0;
        for(int i = 0; i <= MAX; i ++){
            int now = 0;
            for(int j = 1, w = 1; j <= n; j ++, w <<= 1){
                if((w&i) == 0){now = j;break;}
            }
            if(now == 0) continue;
            dp[i|(1<<(now-1))] = min(dp[i|(1<<(now-1))], dp[i] + 1);
            for(int j = 1; j <= num[now][0]; j ++){
                dp[i|num[now][j]] = min(dp[i|num[now][j]], dp[i] + 1);
            }
        }
        printf("%d\n", dp[MAX]);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值