zoukankan      html  css  js  c++  java
  • 2018年东北农业大学春季校赛 题解

    题目链接

    写在前面:从都到尾做了一下这场比赛,似乎好题都是原题,水题都是他们学校自己出的。原题在抄过来的过程中,很多题目的题面、数据范围都出了问题,还有题目数据很水。建议以后这样的比赛不要挂到外面来了,不然别人会骂你们学校不负责任的... ...

    A - wyh的曲线

    吐槽:

    1. 牛客网题面上输入顺序写错了,明明是按 k,a,b 的顺序输入,题面上缺写了以 a,b,k 的顺序输入。

    2. 数据很水,我用精确度非常低的方法能水过去

    3. 建议将代码提交到原题上进行测评:HDU 4498

    精确第很低的方法牛客网上水过:

    #include <bits/stdc++.h>
    using namespace std;
     
    const double eps = 1e-8;
    const int maxn = 1e5 + 10;
    const int INF = 0x7FFFFFFF;
     
    int n;
    double k[maxn], a[maxn], b[maxn];
     
    double f(double x) {
      double res = 100.0;
        for(int i = 1; i <= n; i ++) {
          res = min(res, 1.0 * k[i] * (x - a[i]) * (x - a[i]) + 1.0 * b[i]);
        }
        return res;
    }
     
    double dis(double x1, double y1, double x2, double y2) {
        return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }
     
    double cal(double L, double R) {
      return dis(L, f(L), R, f(R));
    }
     
    double work(double L, double R) {
    //  printf("[%.2f, %.2f]
    ", L, R);
        double mid = (L + R) / 2;
        if(R - L > 0.005) {
            return work(L, mid) + work(mid, R);
        }
        double s0 = cal(L, mid);
        double s1 = cal(mid, R);
        double s2 = cal(L, R);
        if(fabs(s0 + s1 - s2) < eps) return s0 + s1;
        return work(L, mid) + work(mid, R);
    }
     
    int main() {
     
    //  freopen("test.in", "r", stdin);
     
         
          scanf("%d", &n);
            for(int i = 1; i <= n; i ++) {
              scanf("%lf%lf%lf", &k[i], &a[i], &b[i]);
            }
            printf("%.2f
    ", work(0.0, 100.0));
         
         
        return 0;
    }
    

    正解:求出所有抛物线之间的交点,相邻两个交点之间必然有一条曲线需要统计到答案中去,设抛物线方程为 $f(x)$,那么 $[L, R]$ 的曲线长度为 $int _{ L }^{ R }{ sqrt { { f^{ ' }left( x ight)  }^{ 2 }+1 } dx } $。利用自适应 simpson 积分公式加上分治即可。

    #include <bits/stdc++.h>
    using namespace std;
     
    const double eps = 1e-8;
    const int maxn = 1e5 + 10;
    const int INF = 0x7FFFFFFF;
     
    int n;
    double k[maxn], a[maxn], b[maxn];
    vector<double> vec;
     
    double f(double x) {
        double res = 100.0;
        for(int i = 1; i <= n; i ++) {
            res = min(res, k[i] * (x - a[i]) * (x - a[i]) + b[i]);
        }
        return res;
    }
     
    void h(int x, int y) {
        double ta = (k[x]) - (k[y]);
        double tb = (-k[x] * a[x] * 2.0) - (-k[y] * a[y] * 2.0);
        double tc = (k[x] * a[x] * a[x] + b[x]) - (k[y] * a[y] * a[y] + b[y]);
     
        double delta = tb * tb - 4.0 * ta * tc;
        if(delta < 0) return;
     
        double x1 = (-tb - sqrt(delta)) / (2.0 * ta);
        double x2 = (-tb + sqrt(delta)) / (2.0 * ta);
     
        if(x1 >= 0.0 && x1 <= 100.0) vec.push_back(x1);
        if(x2 >= 0.0 && x2 <= 100.0) vec.push_back(x2);
    //  printf("%f %f
    ", x1, x2);
    }
     
    double G(double x, int idx) {
        double tmp = 2.0 * k[idx] * x - 2 * a[idx] * k[idx];
        return sqrt(tmp * tmp + 1.0);
    }
     
    double cal(double L, double R, int idx) {
        double res = 0.0;
        res = (R - L) / 6.0 * (G(L, idx) + 4.0 * G((L + R) / 2.0, idx) + G(R, idx));
        return res;
    }
     
    double work(double L, double R, int idx) {
        double mid = (L + R)  /2;
        double s0 = cal(L, mid, idx);
        double s1 = cal(mid, R, idx);
        double s2 = cal(L, R, idx);
        if(fabs(s0 + s1 - s2) < eps) return s0 + s1;
        return work(L, mid, idx) + work(mid, R, idx);
    }
     
    int main() {
     
     
            scanf("%d", &n);
            for(int i = 1; i <= n; i ++) {
                scanf("%lf%lf%lf", &k[i], &a[i], &b[i]);
            }
            b[0] = 100.0;
            n ++;
     
            vec.clear();
            vec.push_back(0.0);
            vec.push_back(100.0);
            for(int i = 0; i < n; i ++) {
                for(int j = i + 1; j < n; j ++) {
                    h(i, j);
                }
            }
            sort(vec.begin(), vec.end());
     
            for(int i = 0; i < vec.size(); i ++) {
        //      printf("%d : %f
    ", i, vec[i]);
            }
     
            double ans = 0.0;
            for(int i = 1; i < vec.size(); i ++) {
                double L = vec[i - 1];
                double R = vec[i];
                double mid = (L + R) / 2;
     
                int idx = 0;
                double Min = 100.0;
                for(int j = 0; j < n; j ++) {
                    if(k[j] * (a[j] - mid) * (a[j] - mid) + b[j] < Min) {
                        Min = k[j] * (a[j] - mid) * (a[j] - mid) + b[j];
                        idx = j;
                    }
                }
        //      printf("[%lf, %lf], %d ", L, R, idx);
        //      printf(" len : %lf
    ", work(L, R, idx));
                ans = ans + work(L, R, idx);
            }
            printf("%.2f
    ", ans);
         
        return 0;
    }
    

    B - wyh的矩阵

    手算一下前几项就能找到规律了,答案是一个数的平方,那个数有规律。

    #include <bits/stdc++.h>
    using namespace std;
     
    long long a[100010];
     
    void init() {
      a[3] = 5;
      long long cha = 8;
      for(int i = 5; i <= 10000; i = i + 2) {
        a[i] = a[i-2] +cha;
        cha = cha + 4;
      }
    }
     
    int main() {
      init();
      int T;
      int n;
      scanf("%d", &T);
      while(T--) {
        scanf("%d", &n);
        printf("%lld
    ", a[n]*a[n]);
      }
      return 0;
    }
    

    C - wyh的商机

    吐槽:牛客网数据有点水,建议提交到原题 POJ 3728 进行测评

    从 $u$ 走到 $v$ 的最大收益分三种情况:

    1. $[u, lca(u,v)]$ 进行买卖

    2. $[lca(u,v), v]$ 进行买卖

    3. $[u, lca(u,v)]$ 进行买,$[lca(u,v), v]$ 进行卖

    倍增预处理从 $i$ 节点,往上走 $2^j$ 步的最大值,最小值,最大收益,倒着走下来的最大收益四个值就可以进行询问了。

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <cstring>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    const int INF = 0x7FFFFFFF;
     
    int n,  w[maxn];
    int h[maxn], nx[maxn], to[maxn];
    int sz;
     
    int f[maxn][20];
    int Min[maxn][20];
    int Max[maxn][20];
    int Up[maxn][20];
    int Down[maxn][20];
    int dep[maxn], vis[maxn];
     
    void add(int x, int y) {
        to[sz] = y;
        nx[sz] = h[x];
        h[x] = sz ++;
    }
     
    void dfs(int x,int fa) {
        vis[x] = 1;
     
        if(fa == -1) dep[x] = 1;
        else dep[x] = dep[fa] + 1;
     
        f[x][0] = x;
        f[x][1] = fa;
        for(int i = 2; i < 18; i ++) {
            f[x][i] = -1;
            if((1 << i) <= dep[x]) {
                f[x][i] = f[f[f[x][i - 1]][1]][i - 1];
            }
        }
     
        Min[x][0] = w[x];
        Max[x][0] = w[x];
        Up[x][0] = 0;
        Down[x][0] = 0;
        for(int i = 1; i < 18; i ++) {
            if((1 << i) > dep[x]) continue;
            Min[x][i] = min(Min[x][i - 1], Min[f[f[x][i - 1]][1]][i - 1]);
            Max[x][i] = max(Max[x][i - 1], Max[f[f[x][i - 1]][1]][i - 1]);
            Up[x][i] = max(max(Up[x][i - 1], Up[f[f[x][i - 1]][1]][i - 1]),
                    Max[x][i - 1] - Min[f[f[x][i - 1]][1]][i - 1]);
            Down[x][i] = max(max(Down[x][i - 1], Down[f[f[x][i - 1]][1]][i - 1]),
                    Max[f[f[x][i - 1]][1]][i - 1] - Min[x][i - 1]);
        }
     
        for(int i = h[x]; i != -1; i = nx[i]) {
            if(vis[to[i]]) continue;
            dfs(to[i], x);
        }
    }
     
    int LCA(int x, int y) {
        if(dep[x] < dep[y]) {
            swap(x, y);
        }
     
        int pre = 17;
        while(dep[x] != dep[y]) {
            for(int j = pre; j >= 0; j --) {
                if(f[x][j] == -1) continue;
                if(dep[f[x][j]] < dep[y]) continue;
                x = f[x][j];
                pre = j;
                break;
            }
        }
     
        if(x == y) return x;
     
        pre = 17;
        while(f[x][1] != f[y][1]) {
            for(int j = pre; j >= 0; j --) {
                if(f[x][j] == f[y][j]) continue;
                x = f[x][j];
                y = f[y][j];
                pre = j;
                break;
            }
        }
     
        x = f[x][1];
        return x;
    }
     
    int GetMax(int x, int y) {
        int res = w[x];
        int pre = 17;
        while(x != y) {
            for(int j = pre; j >= 0; j --) {
                if(f[x][j] == -1) continue;
                if(dep[f[x][j]] < dep[y]) continue;
                res = max(res, Max[x][j]);
                x = f[x][j];
                pre = j;
                break;
            }
        }
        return res;
    }
     
    int GetMin(int x, int y) {
        int res = w[x];
        int pre = 17;
        while(x != y) {
            for(int j = pre; j >= 0; j --) {
                if(f[x][j] == -1) continue;
                if(dep[f[x][j]] < dep[y]) continue;
                res = min(res, Min[x][j]);
                x = f[x][j];
                pre = j;
                break;
            }
        }
        return res;
    }
     
    int GetMaxUp(int x, int y) {
        if(x == y) return 0;
        int res = 0;
        for(int j = 17; j >= 0; j --) {
            if(f[x][j] == -1) continue;
            if(dep[f[x][j]] < dep[y]) continue;
            if(dep[f[x][j]] == dep[y]) return Up[x][j];
            res = max(Up[x][j], GetMaxUp(f[f[x][j]][1] ,y));
            res = max(res, GetMax(x, f[x][j]) - GetMin(f[f[x][j]][1], y));
            break;
        }
        return res;
    }
     
    int GetMaxDown(int x, int y) {
        if(x == y) return 0;
        int res = 0;
        for(int j = 17; j >= 0; j --) {
            if(f[x][j] == -1) continue;
            if(dep[f[x][j]] < dep[y]) continue;
            if(dep[f[x][j]] == dep[y]) return Down[x][j];
            res = max(Down[x][j], GetMaxDown(f[f[x][j]][1] ,y));
            res = max(res, GetMax(f[f[x][j]][1], y) - GetMin(x, f[x][j]));
            break;
        }
        return res;
    }
     
    int main() {
     
    //  freopen("test.in", "r", stdin);
     
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) {
            scanf("%d", &w[i]);
            h[i] = -1;
        }
        for(int i = 1; i < n; i ++) {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            add(y, x);
        }
        dfs(1, -1);
     
    /*
        for(int i = 1; i <= n; i ++) {
            printf("Node : %d
    ", i);
            for(int j = 0; j < 30; j ++) {
                printf("%d  to : %d, Min : %d, Max : %d, Up : %d, Down : %d
    ", j, f[i][j], Min[i][j], Max[i][j],
                        Up[i][j], Down[i][j]);
            }
        }
    */
     
        int Q;
        scanf("%d", &Q);
        while(Q --) {
            int x, y, lca;
            scanf("%d%d", &x, &y);
            /* x -> y */
            lca = LCA(x, y);
        //  cout << x << " " << y << ", lca : " << lca << endl;
            int ans = 0;
            ans = max(ans, GetMax(y, lca) -  GetMin(x, lca));
            ans = max(ans, GetMaxDown(x, lca));
            ans = max(ans, GetMaxUp(y, lca));
            printf("%d
    ", ans);
        }
     
        return 0;
    }
    

    D - wyh的迷宫

    BFS 一下就好了。

    #include <bits/stdc++.h>
    using namespace std;
    
    int T, n, m;
    char s[600][600];
    int f[600][600];
    int sx, sy, ex, ey;
    
    int dir[4][2] = {
      {-1, 0},
      {1, 0},
      {0, -1},
      {0, 1},
    };
    
    int out(int x, int y) {
      if(x < 0 || x >= n) return 1;
      if(y < 0 || y >= m) return 1;
      return 0;
    }
    
    int main() {
      scanf("%d", &T);
      while(T--) {
        memset(f, 0, sizeof f);
        scanf("%d%d",&n,&m);
        for(int i = 0; i < n; i ++) {
          scanf("%s", s[i]);
          for(int j = 0; j < m; j ++) {
            if(s[i][j] == 's') sx = i, sy = j;
            if(s[i][j] == 't') ex = i, ey = j;
          }
        }
        
        
        queue<pair<int, int> > q;
        q.push(make_pair(sx, sy));
        f[sx][sy] = 1;
        
        while(!q.empty()) {
          pair<int, int> tp = q.front();
          q.pop();
         // cout << tp.first << " " << tp.second << endl;
          for(int i = 0; i < 4; i ++) {
            int nx = tp.first + dir[i][0];
            int ny = tp.second + dir[i][1];
            if(out(nx,ny)) continue;
            if(s[nx][ny] == 'x') continue;
            if(f[nx][ny]) continue;
            q.push(make_pair(nx, ny));
            f[nx][ny] = 1;
          }
          
        }
        
        if(f[ex][ey]) printf("YES
    ");
        else printf("NO
    ");
        
      }
      return 0;
    }
    

    E - wyh的阶乘

    看 $[1,n]$ 这些数素因子分解后,2 的个数和 5 的个数的较小值,显然 5 比 2 少,只要统计 5 的个数就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    
    int T;
    char s[100010];
    
    int find(int n){
      int count= 0;
      while(n > 0){
        count += n / 5;
        n = n / 5;
      }
      return count;
    }
    
    int main() {
      scanf("%d",&T);
      while(T--) {
        long long n;
        scanf("%lld",&n);
        printf("%lld
    ", find(n));
      }
      return 0;
    }
    

    F - wyh的集合

    两边个数差值越少乘积越大。

    #include <bits/stdc++.h>
    using namespace std;
     
    int main() {
      int T;
      long long n;
      scanf("%d", &T);
      while(T--) {
        scanf("%lld", &n);
        if(n == 0 || n == 1) {
          printf("%d
    ", 0);
        } else {
          long long x = n/2;
          long long y = n-n/2;
          printf("%lld
    ", x* y);
        }
      }
      return 0;
    }
    

    G - wyh的考核

    考虑每个人对答案做出的贡献,每个人对答案都贡献都是一样的。

    假设 $n$ 个人总共打了 $s$ 分,平均值 $ave = frac { s }{ n } $,我们只要让一个人打平均分,然后去看剩下的 $n-1$ 个人打 $s - ave$ 分有几种方案,这个可以 $dp$ 得到。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int mod = 1000000007;
    const int maxn = 1e5 + 10;
    const int INF = 0x7FFFFFFF;
     
    int T;
    int n, m;
     
    int f[70][13000];
    int sum[13000];
     
    int GetPos(int x) {
        if(x < 0) return 0;
        return sum[x];
    }
     
    int Get(int L, int R) {
        //  cout << L << " " << R << endl;
        return (GetPos(R) - GetPos(L - 1) + mod) % mod;
    }
     
    void init() {
        memset(f, 0, sizeof f);
        f[0][0] = 1;
        for(int i = 0; i <= 12000; i ++) {
            sum[i] = 1;
        }
        for(int i = 1; i <= n; i ++) {
            for(int j = 0; j <= i * m; j ++) {
                f[i][j] = Get(j - min(m, j), j);
     
                /*
                     for(int k = 0; k <= min(m, j); k ++) {
                     f[i][j] = (f[i][j] + f[i - 1][j - k]) % mod;
                     }
                 */
     
            }
            sum[0] = f[i][0];
            for(int j = 1; j <= 12000; j ++) {
                sum[j] = (sum[j - 1] + f[i][j]) % mod;
            }
        }
    }
     
    int main() {
        //freopen("test.in", "r", stdin);
        scanf("%d", &T);
        while(T --) {
            scanf("%d%d", &n, &m);
            init();
            int ans = 0;
            for(int s = 0; s <= n * m; s ++) {
                if(s % n) continue;
                int ave = s / n;
                long long tmp = 1LL * f[n - 1][s - ave] * n % mod;
                ans = (ans + tmp) % mod;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

    H - wyh的吃鸡

    主要注意安全区域是一个连通块即可,并非一个格子,有可能是一群格子。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1010;
    const int INF = 0x7FFFFFFF;
    char s[maxn][maxn];
    int n, k;
    
    int sx, sy;
    int ex, ey;
    
    int dis[maxn][maxn][2];
    int f[maxn][maxn][2];
    
    int dir[4][2] = {
      {1, 0},
      {-1, 0},
      {0, 1},
      {0, -1}
    };
    
    int out(int x, int y) {
      if(x < 0 || x >= n) return 1;
      if(y < 0 || y >= n) return 1;
      return 0;
    }
    
    int main() {
      int T;
      scanf("%d", &T);
      while(T--) {
        scanf("%d%d", &n, &k);
        for(int i = 0; i < n; i ++) {
          scanf("%s", s[i]);
        }
        
        if(n > 100) while(1) {}
        int sum = 0;
        sx = sy = ex = ey = -1;
        for(int i = 0; i < n; i ++) {
          for(int j = 0; j < n; j ++) {
            if(s[i][j] == 'S') sx = i, sy = j;
            if(s[i][j] == 'X') sum++, ex = i, ey = j;
            dis[i][j][0] = dis[i][j][1] = INF;
          }
        }
        
      //  if(sum != 1) while(1) {}
        
        if(sx == -1 || sy == -1 || ex == -1 || ey == -1){
          while(1) {}
        }
        
        queue<int> qx;
        queue<int> qy;
        queue<int> qc;
        
        qx.push(sx);
        qy.push(sy);
        qc.push(0);
        
        memset(f, 0, sizeof f);
        dis[sx][sy][0] = 0;
        f[sx][sy][0] = 1;
        
        while(!qx.empty()) {
          
          int nx = qx.front();
          int ny = qy.front();
          int nc = qc.front();
          
          qx.pop();
          qy.pop();
          qc.pop();
          
         // cout << nx<<" " << ny << " " <<nc<<endl;
          
          f[nx][ny][nc] = 0;
          
          for(int i = 0; i < 4; i ++) {
            int tx = nx + dir[i][0];
            int ty = ny + dir[i][1];
            int tc = nc;
            
            if(out(tx, ty)) continue;
            if(s[tx][ty] == 'O') continue;
            
            if(s[tx][ty] == 'C') tc = 1;
            
           // cout << tx<<" " << ty << " " <<tc<<endl;
            
            int cost;
            if(nc == 0) cost = 2;
            else cost = 1;
            
            if(dis[nx][ny][nc] + cost < dis[tx][ty][tc]) {
              dis[tx][ty][tc] = dis[nx][ny][nc] + cost;
              if(f[tx][ty][tc] == 0) {
                f[tx][ty][tc] = 1;
                qx.push(tx);
                qy.push(ty);
                qc.push(tc);
    
              }
            }
            
          }
        }
        
        int ans = INF;
        for(int i = 0; i < n; i ++) {
          for(int j = 0; j < n; j ++) {
            if(s[i][j] == 'X') {
              ans = min(ans, dis[i][j][0]);
              ans = min(ans, dis[i][j][1]);
            }
          }
        }
        
        if(ans > k) {
          printf("NO
    ");
        } else {
          printf("YES
    ");
          printf("%d
    ", ans);
        }
        
      }
      return 0;
    }
    
    
    /*
    1
     10 100
     ..........
     ..........
     .......X..
     ..........
     ..........
     ..........
     ..........
     ..S.......
     ..........
     ..........
     
     */
    

    I - wyh的物品

    经典的 01 分数规划。首先有一个单调性,比例越小越可能构造出来,比例越大越不可能构造出来,外面只要验证大于等于 $x$ 的比例能不能构造出来,如果可以,答案会更大,否则答案会更小,因此可以二分 $x$,然后进行验证。

    验证 $frac { sum { b }  }{ sum { a }  } ge x $ 是否可行,等价于验证 $sum { b } -xsum { a } ge 0$ 是否可行。另 ${ c }_{ i } = { b }_{ i }-x*{ a }_{ i }$,只要取最大的 $k$ 个 $c$,看 $sum$ 是否大于等于 0 即可。

    #include <bits/stdc++.h>
    using namespace std;
     
    const int maxn = 1e5 + 10;
    const int INF = 0x7FFFFFFF;
     
    int T, n, k;
    double a[maxn], b[maxn], c[maxn];
     
    int check(double x) {
        for(int i = 1; i <= n; i ++) {
          c[i] = b[i] - x * a[i];
        }
        sort(c + 1, c + 1 + n);
        double sum = 0.0;
        for(int i = n; i >= n - k + 1; i --) {
          sum = sum + c[i];
        }
        if(sum >= 0) return 1;
        return 0;
    }
     
    int main() {
       
    //  freopen("test.in", "r", stdin);
     
        scanf("%d", &T);
        while(T --) {
            scanf("%d%d", &n, &k);
            for(int i = 1; i <= n; i ++) {
              scanf("%lf%lf", &a[i], &b[i]);
            }
            double L = 0, R = 1e18, ans;
            for(int it = 1; it <= 100; it ++) {
                double mid = (L + R) / 2;
                if(check(mid)) {
                  ans = mid;
                    L = mid;
                } else {
                  R = mid;
                }
            }
            printf("%.2f
    ", ans);
        }
        return 0;
    }
    

    J - wyh的问题

    吐槽:牛客网上数据错了,我多次和出题人说,他不信。建议提交到原题进行测评:NYOJ 304

    如果数据没有错,下面这个代码怎么会超时?感觉出(chao)题人很逗啊... ...

    #include <bits/stdc++.h>
    using namespace std;
      
    const long long limit = 1e9;
    const long long INF = limit * limit;
    struct X {
      int id;
      long long d, w;
    }s[1010];
    int n;
    int id;
      
    bool cmp(const X&a, const X&b) {
      return a.d < b.d;
    }
      
    long long dp[1010][1010][2];
      
    long long sum[1010];
      
    long long cal(int x1, int y1, int x2, int y2) {
      return sum[y1] - sum[x1 - 1] - (sum[y2] - sum[x2 - 1]);
    }
      
    int main() {
      while(~scanf("%d%d", &n, &id)) {
        for(int i = 1; i <= n; i ++) {
          scanf("%lld%lld", &s[i].d, &s[i].w);
          sum[i] = sum[i - 1] + s[i].w;
          s[i].id = i;
            if(i > 1 && s[i].d < s[i-1].d) while(1) {}
        }
         
      }
      return 0;
    }
    

    正解:

    可以观察到如果他从起点出发关了某盏灯,那么途径的灯都会被关掉,也就是从起点往两边跑来跑去关灯的过程,很明显是个区间 dp,记录一下关完某个区间的灯,在左端点还有右端点的最小耗电量即可。

    #include <bits/stdc++.h>
    using namespace std;
     
    const long long limit = 1e9;
    const long long INF = limit * limit;
    struct X {
      int id;
      long long d, w;
    }s[1010];
    int n;
    int id;
     
    bool cmp(const X&a, const X&b) {
      return a.d < b.d;
    }
     
    long long dp[1010][1010][2];
     
    long long sum[1010];
     
    long long cal(int x1, int y1, int x2, int y2) {
      return sum[y1] - sum[x1 - 1] - (sum[y2] - sum[x2 - 1]);
    }
     
    int main() {
      while(~scanf("%d%d", &n, &id)) {
        for(int i = 1; i <= n; i ++) {
          scanf("%lld%lld", &s[i].d, &s[i].w);
          sum[i] = sum[i - 1] + s[i].w;
          s[i].id = i;
        }
         
        for(int i = 1; i <= n; i ++) {
          for(int j = i; j <= n; j ++) {
            dp[i][j][0] = INF;
            dp[i][j][1] = INF;
          }
        }
         
        dp[id][id][0] = dp[id][id][1] = 0;
         
        for(int len = 2; len <= n; len ++) {
          for(int L = 1; L <= n; L ++) {
            int R = L + len - 1;
            if(R > n) break;
             
            // cal [L][R][0]
             
              // [L, R - 1][0]
            if(dp[L][R - 1][0] != INF)
            dp[L][R][0] = min(dp[L][R][0],
                              dp[L][R - 1][0]
                              + (s[R].d - s[L].d) * cal(1, n, L, R - 1)
                              + (s[R].d - s[L].d) * cal(1, n, L, R));
              // [L, R - 1][1]
            if(dp[L][R - 1][1] != INF)
            dp[L][R][0] = min(dp[L][R][0],
                              dp[L][R - 1][1]
                              + (s[R].d - s[R - 1].d) * cal(1, n, L, R - 1)
                              + (s[R].d - s[L].d) * cal(1, n, L, R));
              // [L + 1, R][0]
            if(dp[L + 1][R][0] != INF)
            dp[L][R][0] = min(dp[L][R][0],
                              dp[L + 1][R][0]
                              + (s[L + 1].d - s[L].d) * cal(1, n, L + 1, R));
              // [L + 1, R][1]
            if(dp[L + 1][R][1] != INF)
            dp[L][R][0] = min(dp[L][R][0],
                              dp[L + 1][R][1]
                              + (s[R].d - s[L].d) * cal(1, n, L + 1, R));
             
            // cal [L][R][1]
             
              // [L, R - 1][0]
            if(dp[L][R - 1][0] != INF)
            dp[L][R][1] = min(dp[L][R][1],
                              dp[L][R - 1][0]
                              + (s[R].d - s[L].d) * cal(1, n, L, R - 1));
              // [L, R - 1][1]
            if(dp[L][R - 1][1] != INF)
            dp[L][R][1] = min(dp[L][R][1],
                              dp[L][R - 1][1]
                              + (s[R].d - s[R - 1].d) * cal(1, n, L, R - 1));
              // [L + 1, R][0]
            if(dp[L + 1][R][0] != INF)
            dp[L][R][1] = min(dp[L][R][1],
                              dp[L + 1][R][0]
                              + (s[L + 1].d - s[L].d) * cal(1, n, L + 1, R)
                              + (s[R].d - s[L].d) * cal(1, n, L, R));
              // [L + 1, R][1]
            if(dp[L + 1][R][1] != INF)
            dp[L][R][1] = min(dp[L][R][1],
                              dp[L + 1][R][1]
                              + (s[R].d - s[L].d) * cal(1, n, L + 1, R)
                              + (s[R].d - s[L].d) * cal(1, n, L, R));
          }
        }
        printf("%lld
    ", min(dp[1][n][0], dp[1][n][1]));
      }
      return 0;
    }
    

    K - wyh的数列

    去寻找 $f_i=0$, $f_{i+1}=1$的除 0 之外的最小 $i$,找到了这个就找到了循环节。

    #include <bits/stdc++.h>
    using namespace std;
    
    unsigned long long f[5000];
    
    unsigned long long a, b;
    unsigned long long c;
    
    unsigned long long qpow(unsigned long long a, unsigned long long b, unsigned long long mod) {
      unsigned long long res = 1;
      
      a = a % mod;
      while(b) {
        if(b % 2 == 1) {
          res = (res * a) % mod;
        }
        a = (a * a) % mod;
        b = b / 2;
      }
      return res;
    }
    
    int main() {
      int T;
      scanf("%d", &T);
      while(T--) {
        cin >> a >> b >> c;
        f[0] = 0;
        f[1] = 1;
        unsigned long long limit;
        for(int i = 2; ; i ++) {
          f[i] = (f[i-1]+ f[i-2]) % c;
          
          if(f[i] == 1 && f[i-1] == 0) {
            limit = i;
            break;
          }
        }
        
        //[0, limit - 2]
       
        cout << f[qpow(a, b, limit - 1)] << endl;
        
      }
      return 0;
    }
    
    
    /*
    
     
     3
     1 1 2
     2 3 1000
     32122142412412142 124124124412124 123
     
     */
    

    L - wyh的天鹅

    吐槽:打开题目,看到萌值没有数据范围,问了一下出(chao)题人,说是在 $[1, 10^5]$,然后我开始写,写完提交,返回错误,看了好久代码,看不出毛病,然后我就在想可能优秀的出(chao)题人告诉我的数据范围是骗我的,因此我扩大到了 $10^6$,提交返回正确。CNMLGB ?后来出题人在题面上 update 了数据范围:$[1,1000000000]$,再一次骗我?我开到 $10^6$ 是怎么过的?

    题解:经典的权值线段树,直接在线段树上选择往右走还是往左走就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6+10;
    int T;
    
    int s[maxn * 4];
    
    char op[20];
    int n, m;
    int ans;
    
    void build(int l, int r, int rt) {
      s[rt] = 0;
      if(l == r) return;
      int mid = (l+r)/2;
      build(l, mid, 2*rt);
      build(mid+1, r, 2*rt+1);
    }
    
    void update(int pos, int val, int l, int r, int rt) {
      if(l == r) {
        s[rt] += val;
        return;
      }
      int mid = (l+r)/2;
      if(pos <= mid) update(pos, val, l, mid, 2 * rt);
      else update(pos, val, mid+1, r, 2*rt+1);
      s[rt] = s[2*rt]+s[2*rt+1];
    }
    
    void query(int k, int l, int r, int rt) {
      if(l == r) {
        ans = l;
        return;
      }
      int mid = (l+r)/2;
      if(s[2*rt+1] >= k) query(k,mid+1,r,2*rt+1);
      else query(k - s[2*rt+1],l,mid,2*rt);
    }
    
    int main() {
      scanf("%d",&T);
      while(T--) {
        scanf("%d%d",&n,&m);
        build(0,1e6,1);
        for(int i = 1; i <= n; i ++) {
          int x;
          scanf("%d",&x);
          if(x > 1e6) while(1) {}
          update(x,1,0,1e6,1);
        }
        
        while(m--) {
          scanf("%s", op);
          int x;
          scanf("%d", &x);
          if(op[0] == 'q') {
            query(x,0,1e6,1);
            printf("%d
    ", ans);
          } else if(op[0] == 'i') {
            if(x > 1e6) while(1) {}
            update(x, 1, 0, 1e6, 1);
          } else {
            if(x > 1e6) while(1) {}
            update(x, -1, 0, 1e6, 1);
          }
        }
        
      }
      return 0;
    }
    

    M - wyh的数字

    水题。

    #include <bits/stdc++.h>
    using namespace std;
    
    int T;
    char s[100010];
    
    int main() {
      scanf("%d",&T);
      while(T--) {
        scanf("%s",s);
        int ans = 0;
        for(int i = 0; s[i];i++){
          if(s[i] == '7') ans++;
        }
        cout << ans <<endl;
      }
      return 0;
    }
    
  • 相关阅读:
    Nvidia TX2 Robot 环境配置记录
    [DL学习笔记]从人工神经网络到卷积神经网络_2_卷积神经网络
    [DL学习笔记]从人工神经网络到卷积神经网络_1_神经网络和BP算法
    windows重建图标缓存(解决快捷方式图标丢失,图标加载时间长问题)
    tensorflow安装日志(PIP)
    java中字符串的排序(1)
    可行性分析报告
    冒泡,选择,插入,快速排序在Java中的实现
    四则运算法则在Java中的实现
    关于二次方程计算器的程序开发
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8757702.html
Copyright © 2011-2022 走看看