zoukankan      html  css  js  c++  java
  • bupt summer training for 16 #3 ——构造

    https://vjudge.net/contest/172464

    后来补题发现这场做的可真他妈傻逼

    A.签到傻逼题,自己分情况

     1 #include <cstdio>
     2 #include <vector>
     3 #include <algorithm>
     4 
     5 using std::vector;
     6 using std::sort;
     7 
     8 typedef long long ll;
     9 
    10 int n, m;
    11 
    12 ll a[2100], b[2100];
    13 
    14 ll sa, sb, dis, tmp, qaq;
    15 
    16 int t1 = -1, t2 = -1;
    17 
    18 int a1, a2, a3, a4;
    19 
    20 struct node {
    21     ll x, y, z;
    22     bool operator < (const node &a) const {
    23         return x < a.x;
    24     }
    25 };
    26 
    27 vector <node> e;
    28 
    29 ll abs(ll x) {
    30     return x < 0 ? -x : x;
    31 }
    32 
    33 node find1(ll x) {
    34     node ret = {0, -1, -1};
    35     int l = 0, r = e.size() - 1, mid;
    36     while(l <= r) {
    37         int mid = (l + r) >> 1;
    38         if(e[mid].x * 2 <= x) ret = e[mid], l = mid + 1;
    39         else r = mid - 1;
    40     }
    41     return ret;
    42 }
    43 
    44 node find2(ll x) {
    45     node ret = {0, -1, -1};
    46     int l = 0, r = e.size() - 1, mid;
    47     while(l <= r) {
    48         int mid = (l + r) >> 1;
    49         if(e[mid].x * 2 > x) ret = e[mid], r = mid - 1;
    50         else l = mid + 1;
    51     }
    52     return ret;
    53 }
    54 
    55 int main() {
    56     scanf("%d", &n);
    57     for(int i = 1;i <= n;i ++)
    58         scanf("%lld", &a[i]), sa += a[i];
    59     scanf("%d", &m);
    60     for(int i = 1;i <= m;i ++)
    61         scanf("%lld", &b[i]), sb += b[i];
    62     if(abs(sa - sb) <= 1) {
    63         printf("%lld
    0
    ", abs(sa - sb));
    64         return 0;
    65     }
    66     qaq = tmp = dis = sa - sb;
    67     for(int i = 1;i <= n;i ++) 
    68         for(int j = 1;j <= m;j ++)
    69             if(abs(qaq - (a[i] - b[j]) * 2) < abs(dis))
    70                 dis = qaq - (a[i] - b[j]) * 2, t1 = i, t2 = j;
    71     for(int i = 1;i <= n;i ++)
    72         for(int j = i + 1;j <= n;j ++)
    73             e.push_back((node){a[i] + a[j], i, j});
    74     sort(e.begin(), e.end());
    75     for(int i = 1;i <= m;i ++)
    76         for(int j = i + 1;j <= m;j ++) {
    77             ll k = b[i] + b[j];
    78             node tt = find1(qaq + k * 2);
    79             if(tt.y != -1 && abs(qaq + k * 2 - tt.x * 2) < abs(tmp)) tmp = qaq + k * 2 - tt.x * 2, a1 = tt.y, a2 = i, a3 = tt.z, a4 = j;
    80             tt = find2(qaq + k * 2);
    81             if(tt.y != -1 && abs(qaq + k *  2 - tt.x * 2) < abs(tmp)) tmp = qaq + k * 2 - tt.x * 2, a1 = tt.y, a2 = i, a3 = tt.z, a4 = j;
    82         }
    83     if(abs(qaq) <= abs(dis) && abs(qaq) <= abs(tmp)) printf("%lld
    0
    ", abs(qaq));
    84     else if(abs(dis) <= abs(tmp)) printf("%lld
    1
    %d %d", abs(dis), t1, t2);
    85     else printf("%lld
    2
    %d %d
    %d %d", abs(tmp), a1, a2, a3, a4);
    86     return 0;
    87  }
    View Code

    想写if-else结果写完if忘记else了

    B.我是暴力的O(n^2logn)

    首先如果只交换一个数,那O(n^2)都会算吧

    那交换两个数呢,我把n个数两两结合并求和,再对他们排序

    再枚举另一数组的数对,二分一下尝试更新答案

     1 #include <cstdio>
     2 #include <vector>
     3 #include <algorithm>
     4 
     5 using std::vector;
     6 using std::sort;
     7 
     8 typedef long long ll;
     9 
    10 int n, m;
    11 
    12 ll a[2100], b[2100];
    13 
    14 ll sa, sb, dis, tmp, qaq;
    15 
    16 int t1 = -1, t2 = -1;
    17 
    18 int a1, a2, a3, a4;
    19 
    20 struct node {
    21     ll x, y, z;
    22     bool operator < (const node &a) const {
    23         return x < a.x;
    24     }
    25 };
    26 
    27 vector <node> e;
    28 
    29 ll abs(ll x) {
    30     return x < 0 ? -x : x;
    31 }
    32 
    33 node find1(ll x) {
    34     node ret = {0, -1, -1};
    35     int l = 0, r = e.size() - 1, mid;
    36     while(l <= r) {
    37         int mid = (l + r) >> 1;
    38         if(e[mid].x * 2 <= x) ret = e[mid], l = mid + 1;
    39         else r = mid - 1;
    40     }
    41     return ret;
    42 }
    43 
    44 node find2(ll x) {
    45     node ret = {0, -1, -1};
    46     int l = 0, r = e.size() - 1, mid;
    47     while(l <= r) {
    48         int mid = (l + r) >> 1;
    49         if(e[mid].x * 2 > x) ret = e[mid], r = mid - 1;
    50         else l = mid + 1;
    51     }
    52     return ret;
    53 }
    54 
    55 int main() {
    56     scanf("%d", &n);
    57     for(int i = 1;i <= n;i ++)
    58         scanf("%lld", &a[i]), sa += a[i];
    59     scanf("%d", &m);
    60     for(int i = 1;i <= m;i ++)
    61         scanf("%lld", &b[i]), sb += b[i];
    62     if(abs(sa - sb) <= 1) {
    63         printf("%lld
    0
    ", abs(sa - sb));
    64         return 0;
    65     }
    66     qaq = tmp = dis = sa - sb;
    67     for(int i = 1;i <= n;i ++) 
    68         for(int j = 1;j <= m;j ++)
    69             if(abs(qaq - (a[i] - b[j]) * 2) < abs(dis))
    70                 dis = qaq - (a[i] - b[j]) * 2, t1 = i, t2 = j;
    71     for(int i = 1;i <= n;i ++)
    72         for(int j = i + 1;j <= n;j ++)
    73             e.push_back((node){a[i] + a[j], i, j});
    74     sort(e.begin(), e.end());
    75     for(int i = 1;i <= m;i ++)
    76         for(int j = i + 1;j <= m;j ++) {
    77             ll k = b[i] + b[j];
    78             node tt = find1(qaq + k * 2);
    79             if(tt.y != -1 && abs(qaq + k * 2 - tt.x * 2) < abs(tmp)) tmp = qaq + k * 2 - tt.x * 2, a1 = tt.y, a2 = i, a3 = tt.z, a4 = j;
    80             tt = find2(qaq + k * 2);
    81             if(tt.y != -1 && abs(qaq + k *  2 - tt.x * 2) < abs(tmp)) tmp = qaq + k * 2 - tt.x * 2, a1 = tt.y, a2 = i, a3 = tt.z, a4 = j;
    82         }
    83     if(abs(qaq) <= abs(dis) && abs(qaq) <= abs(tmp)) printf("%lld
    0
    ", abs(qaq));
    84     else if(abs(dis) <= abs(tmp)) printf("%lld
    1
    %d %d", abs(dis), t1, t2);
    85     else printf("%lld
    2
    %d %d
    %d %d", abs(tmp), a1, a2, a3, a4);
    86     return 0;
    87  }
    View Code

    补题的时候,就把比赛代码三个地方的 int 改成了long long就过了

    C.别人补题写的DP一眼看不懂...反正数据范围也不大,我们来xjb乱搞吧

    数据范围20,时间5s,没有直接爆搜的思路

    答案在0-1之间,满足单调性...试试二分?那judge呢?暴力dfs枚举?

    效率玄学?并没有关系!...就当试试咯...过了...比DP还快...

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const double eps = 1e-14;
     8 
     9 int n, L[21], R[21];
    10 
    11 double a[21];
    12 
    13 bool dfs(int i, int x) {
    14     if(i > n)
    15         return 1;
    16     int y = L[i] / x;
    17     if(L[i] % x) y ++;
    18     for(y *= x;y <= R[i];y += x)
    19         if(dfs(i + 1, y))
    20             return 1;
    21     return 0;
    22 }
    23 
    24 bool judge(double k) {
    25     for(int i = 1;i <= n;i ++)
    26         L[i] = ceil(a[i] - a[i] * k), R[i] = floor(a[i] + a[i] * k);
    27     for(int i = L[1];i <= R[1];i ++)
    28         if(dfs(2, i))
    29             return 1;
    30     return 0;
    31 }
    32 
    33 int main() {
    34     scanf("%d", &n);
    35     for(int i = 1;i <= n;i ++)
    36         scanf("%lf", &a[i]);
    37     double l = 0, r = 1.0, mid, ans;
    38     for(int t = 66;t --;) {
    39         mid = (l + r) / 2;
    40         if(judge(mid)) ans = mid, r = mid - eps;
    41         else l = mid + eps;
    42     }
    43     printf("%.12f", ans);
    44     return 0;
    45 }
    View Code

    看了别人DP代码...看懂了...

    f[i][j]代表把第 i 种货币变成 j 的最小答案

    我们有一种无赖解是把所有货币都变0

    所以对于第 i 种货币,从 0 枚举到 a[i] * 2 就可以啦

    复杂度O(nklogk),  k = max(a[i]) = 20W

    这么来说粗略计算我的做法复杂度就是O(nklogk * log(1/eps))...实际优太多

    D.ans = C(n,3) - 不合法的三角形

    对于非法三角形枚举最大边 z

    再求 x + y <= z 的 (x,y) 有多少对即可

    预处理,O(1)回答

     1 #include <cstdio>
     2 
     3 typedef long long ll;
     4 
     5 const int maxn = 1000010;
     6 
     7 ll a[maxn], b[maxn];
     8 
     9 ll c(ll x) {
    10     return x * (x - 1) * (x - 2) / 6;
    11 }
    12 
    13 int main() {
    14     for(int i = 3;i <= 1000000;i ++) a[i] = (i + 1) / 2 - 1;
    15     for(int i = 4, j = 0;i <= 1000000;i ++) {
    16         if(!(i & 1)) j ++;
    17         b[i] = b[i - 1] + j;
    18     }    
    19     for(int i = 3;i <= 1000000;i ++) a[i] += a[i - 1], b[i] += b[i - 1];
    20     int n;
    21     while(scanf("%d", &n), n >= 3) printf("%lld
    ", c(n) - a[n] - b[n]);
    22     return 0;
    23 }
    View Code

    E.

  • 相关阅读:
    Linux权限及归属管理
    Linux账户管理
    随笔记录 磁盘坏道故障 2019.8.7
    随笔记录 MBR扇区故障系统备份与还原 2019.8.7
    随笔记录 grub引导故障修复 2019.8.7
    随笔记录 综合训练 2019.8.5
    随笔记录 磁盘配额2019.8.2
    随笔记录 2019.7.31
    随笔记录 2019.7.31
    随笔记录 linux命令 2019.7.29
  • 原文地址:https://www.cnblogs.com/ytytzzz/p/7253450.html
Copyright © 2011-2022 走看看