zoukankan      html  css  js  c++  java
  • 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution

    A:Exam

    Solved.

    温暖的签。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e3 + 10;
     6 
     7 int k;
     8 char str1[maxn], str2[maxn];
     9 
    10 int main()
    11 {
    12     while(~scanf("%d",&k))
    13     {
    14         scanf("%s", str1 + 1);
    15         scanf("%s", str2 + 1);
    16         int cnt1 = 0, cnt2 = 0;
    17         int len = strlen(str1 + 1);
    18         for(int i = 1; i <= len; ++i)
    19         {
    20             if(str1[i] == str2[i]) cnt1++;
    21             else cnt2++;
    22         }
    23         int ans = 0;
    24         if(cnt1 >= k)
    25         {
    26             ans = k + cnt2;
    27         }
    28         else 
    29         {
    30             ans = len - (k - cnt1);
    31         }
    32         printf("%d
    ", ans);
    33     }
    34     return 0;
    35 }
    View Code

    B:Coprime Integers

    Solved.

    枚举gcd反演

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const int maxn = 1e7 + 10;
     8 
     9 bool check[maxn];
    10 int prime[maxn];
    11 ll mu[maxn];
    12 
    13 void Moblus()
    14 {
    15     memset(check, false, sizeof check);
    16     mu[1] = 1;
    17     int tot = 0;
    18     for(int i = 2; i < maxn; ++i)
    19     {
    20         if(!check[i])
    21         {
    22             prime[tot++] = i;
    23             mu[i] = -1;
    24         }
    25         for(int j = 0; j < tot; ++j)
    26         {
    27             if(i * prime[j] > maxn) break;
    28             check[i * prime[j]] = true;
    29             if(i % prime[j] == 0)
    30             {
    31                 mu[i * prime[j]] = 0;
    32                 break;
    33             }
    34             else 
    35             {
    36                 mu[i * prime[j]] = -mu[i];
    37             }
    38         }
    39     }
    40 }
    41 
    42 ll sum[maxn];
    43 
    44 ll calc(int n, int m)
    45 {
    46     ll ans = 0;
    47     if(n > m) swap(n, m);
    48     for(int i = 1, la = 0; i <= n; i = la + 1)
    49     {
    50         la = min(n / (n / i), m / (m / i));
    51         ans += (ll)(sum[la] - sum[i - 1]) * (n / i) * (m / i);
    52     }
    53     return ans;
    54 }    
    55 
    56 ll a, b, c, d;
    57 
    58 int main()
    59 {
    60     Moblus();
    61     for(int i = 1; i < maxn; ++i) sum[i] = sum[i - 1] + mu[i];
    62     while(~scanf("%lld %lld %lld %lld", &a, &b, &c, &d))
    63     {
    64         ll ans = calc(b, d) - calc(a - 1, d) - calc(b, c - 1) + calc(a - 1, c - 1);
    65         printf("%lld
    ", ans);
    66     }
    67     return 0;
    68 }
    View Code

    C:Contest Setting

    Solved.

    题意:

    有n个题目,每个题目的难度值不同,要选出k个组成一套$Contest$

    要求每个题目难度不同,求方案数

    思路:

    $把难度值相同的题目放在一起作为一种 dp[i][j] 表示选到第i种题目,已经选了k种的方案数$

    $然后做01背包即可,注意加上的值为cnt[i] 表示该种题目有多少个$

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll MOD = 998244353;
     8 const int maxn = 1e3 + 10;
     9 
    10 int n, k, pos;
    11 ll cnt[maxn];
    12 ll dp[maxn];
    13 map<int, int>mp;
    14 
    15 int main()
    16 {
    17     while(~scanf("%d %d", &n, &k))
    18     {
    19         mp.clear();
    20         pos = 0;
    21         memset(cnt, 0, sizeof cnt);
    22         for(int i = 1; i <= n; ++i)
    23         {
    24             int num;
    25             scanf("%d", &num);
    26             if(mp[num] == 0) mp[num] = ++pos;
    27             int id = mp[num];
    28             cnt[id]++;
    29         }
    30         memset(dp, 0, sizeof dp);
    31         dp[0] = 1;
    32         for(int i = 1; i <= pos; ++i)
    33         {
    34             for(int j = k; j >= 1; --j)
    35             {
    36                 dp[j] = (dp[j] + dp[j - 1] * cnt[i] % MOD) % MOD;
    37             }
    38         }
    39         printf("%lld
    ", dp[k]);
    40     }
    41     return 0;
    42 }
    View Code

    D:Count The Bits

    Solved.

    题意:

    在$[0, 2^b - 1] 中所有k的倍数以二进制形式表示有多少个1$

    思路:

    $dp[i][j] 表示枚举二进制位数,j 模k的余数, 表示的是前i位中模k的余数为j的数中1的个数$

    $cnt[i][j] 表示当前二进制位为第i位, 模k的余数为j的数的个数$

    直接转移即可。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll MOD = (ll)1e9 + 9;
     8 const int maxn = 1e3 + 10;
     9 
    10 int k, b;
    11 ll cnt[maxn][maxn];
    12 ll dp[maxn][maxn];
    13 
    14 int main()
    15 {
    16     while(~scanf("%d %d", &k, &b))
    17     {
    18         memset(cnt, 0, sizeof cnt);
    19         memset(dp, 0, sizeof dp);
    20         cnt[1][0]++;
    21            cnt[1][1 % k]++;
    22         dp[1][1 % k]++;
    23         ll tmp = 1;
    24         for(int i = 1; i <= b; ++i)
    25         {
    26             tmp = (tmp << 1) % k;
    27             for(int j = 0; j < k; ++j)
    28             {
    29                 //0
    30                 cnt[i + 1][j] = (cnt[i + 1][j] + cnt[i][j]) % MOD;
    31                 dp[i + 1][j] = (dp[i + 1][j] + dp[i][j]) % MOD;
    32                 //1
    33                 ll tmp2 = (tmp + j) % k;
    34                 cnt[i + 1][tmp2] = (cnt[i + 1][tmp2] + cnt[i][j]) % MOD;
    35                 dp[i + 1][tmp2] = ((dp[i + 1][tmp2] + cnt[i][j]) % MOD + dp[i][j]) % MOD;
    36             }
    37         }
    38         printf("%lld
    ", dp[b][0]);
    39     }
    40     return 0;
    41 }
    View Code
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 1010
     5 #define ll long long
     6 const ll MOD = (ll)1e9 + 9;
     7 ll dp[N][N], cnt[N][N];
     8 int n, k;
     9 
    10 int main()
    11 {
    12     while (scanf("%d%d", &k, &n) != EOF)
    13     {
    14         memset(dp, 0, sizeof dp);
    15         memset(cnt, 0, sizeof cnt);
    16         ++dp[1][1 % k];
    17         ++cnt[1][1 % k];
    18         ++cnt[1][0];     
    19         ll tmp = 1 % k;  
    20         for (int i = 2; i <= n; ++i)
    21         {
    22             tmp = tmp * 2 % k; 
    23             for (int j = 0; j < k; ++j) 
    24             {
    25                 dp[i][j] = dp[i - 1][j];   
    26                 cnt[i][j] = cnt[i - 1][j]; 
    27                 if (j - tmp >= 0) 
    28                 {
    29                     dp[i][j] = (dp[i][j] + dp[i - 1][j - tmp] + cnt[i - 1][j - tmp]) % MOD;
    30                     cnt[i][j] = (cnt[i][j] + cnt[i - 1][j - tmp]) % MOD; 
    31                 }
    32                 else 
    33                 {
    34                     dp[i][j] = (dp[i][j] + dp[i - 1][k + j - tmp] + cnt[i - 1][k + j - tmp]) % MOD;
    35                     cnt[i][j] = (cnt[i][j] + cnt[i - 1][k + j - tmp]) % MOD; 
    36                 }
    37             }    
    38         }
    39         printf("%lld
    ", dp[n][0]);
    40     }
    41     return 0;
    42 }
    View Code

    E:Cops And Robbers

    Solved.

    题意:

    在一个$n * m 的矩阵中,有些地方可以建墙,但是不同的墙开销不同,求最小开销把劫匪围住$

    思路:

    拆点最小割,但是是点权,拆点即可。

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std; 
      4 
      5 const int maxn = 4e3 + 10;
      6 const int INF = 0x3f3f3f3f;
      7 
      8 struct Edge{
      9     int to, flow, nxt;
     10     Edge(){}
     11     Edge(int to, int nxt, int flow):to(to), nxt(nxt), flow(flow){}
     12 }edge[maxn << 2];
     13 
     14 int head[maxn], dep[maxn];
     15 int S,T;
     16 int N, n, m, tot;
     17 
     18 void Init(int n)
     19 {
     20     N = n;
     21     //memset(head, -1, sizeof head);
     22     for(int i = 0; i < N; ++i) head[i] = -1;
     23     tot = 0;
     24 }
     25 
     26 void addedge(int u, int v, int w, int rw = 0)
     27 {
     28     edge[tot] = Edge(v, head[u], w); head[u] = tot++;
     29     edge[tot] = Edge(u, head[v], rw); head[v] = tot++;
     30 }
     31 
     32 bool BFS()
     33 {
     34     //memset(dep, -1, sizeof dep);
     35     for(int i = 0; i < N; ++i) dep[i] = -1;
     36     queue<int>q;
     37     q.push(S);
     38     dep[S] = 1;
     39     while(!q.empty())
     40     {
     41         int u = q.front();
     42         q.pop();
     43         for(int i = head[u]; ~i; i = edge[i].nxt)
     44         {
     45             if(edge[i].flow && dep[edge[i].to] == -1)
     46             {
     47                 dep[edge[i].to] = dep[u] + 1;
     48                 q.push(edge[i].to);
     49             }
     50         }
     51     }
     52     return dep[T] < 0 ? 0 : 1;
     53 }
     54 
     55 int DFS(int u, int f)
     56 {
     57     if(u == T || f == 0) return f;
     58     int w, used = 0;
     59     for(int i = head[u]; ~i; i = edge[i].nxt)
     60     {
     61         if(edge[i].flow && dep[edge[i].to] == dep[u] + 1)
     62         {
     63             w = DFS(edge[i].to, min(f - used, edge[i].flow));
     64             edge[i].flow -= w;
     65             edge[i ^ 1].flow += w;
     66             used += w;
     67             if(used == f) return f;
     68         }
     69     }
     70     if(!used) dep[u] = -1;
     71     return used;
     72 }
     73 
     74 int Dicnic()
     75 {
     76     int ans = 0;
     77     while(BFS())
     78     {
     79         int tmp = DFS(S, INF); 
     80         if(tmp == INF) return -1;
     81         ans += tmp;
     82     }
     83     return ans;
     84 }
     85 
     86 int c;
     87 int C[maxn];
     88 char mp[100][100];
     89 
     90 int calc(int i, int j)
     91 {
     92     return i * 31 + j;
     93 }
     94 
     95 int main()
     96 {
     97     while(~scanf("%d %d %d", &m, &n, &c))
     98     {
     99         int base = n * 31 + m + 31;
    100         int x, y;
    101         Init(4000);
    102         for(int i = 1; i <= n; ++i)
    103         {
    104             for(int j = 1; j <= m; ++j)
    105             {
    106                 scanf(" %c", &mp[i][j]);
    107                 if(mp[i][j] == 'B') { x = i, y = j; }
    108             }
    109         }
    110         for(int i = 1; i <= c; ++i) scanf("%d", C + i);
    111         S = 0, T = calc(x, y);
    112         for(int i = 1; i <= n; ++i)
    113         {
    114             addedge(S, calc(i, 1), INF);
    115             addedge(S, calc(i, m), INF);    
    116         }
    117         for(int i = 1; i <= m; ++i)
    118         {
    119             addedge(S, calc(1, i), INF);
    120             addedge(S, calc(n, i), INF);
    121         }
    122         for(int i = 1; i <= n; ++i)
    123         {
    124             for(int j = 1; j <= m; ++j)
    125             {
    126                 if(i != n)
    127                 {
    128                     addedge(calc(i, j) + base, calc(i + 1, j), INF);
    129                     addedge(calc(i + 1, j) + base, calc(i, j), INF);
    130                 }
    131                 if(j != m)
    132                 {
    133                     addedge(calc(i, j)+ base, calc(i, j + 1), INF);
    134                     addedge(calc(i, j + 1) + base, calc(i, j), INF);
    135                 }
    136             }
    137         }
    138         for(int i = 1; i <= n; ++i)
    139         {
    140             for(int j = 1; j <= m; ++j)
    141             {
    142                 if(mp[i][j] >= 'a' && mp[i][j] <= 'z')
    143                 {
    144                     addedge(calc(i, j), calc(i, j) + base, C[mp[i][j] - 'a' + 1]);
    145                 }
    146                 else 
    147                 {
    148                     addedge(calc(i, j), calc(i, j) + base, INF);
    149                 }
    150             }
    151         }
    152         int ans = Dicnic();
    153         printf("%d
    ", ans);
    154     }
    155     return 0;
    156 }
    View Code

    F:Rectangles

    Solved.

    题意:

    二维平面上有一些平行坐标轴的矩形,求有多少区间是被奇数个矩形覆盖。

    思路:

    扫描线,只是把区间加减换成区间01状态翻转,现场学扫描线可还行..

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 #define N 200010
      6 #define pii pair <int, int>
      7 int n, mx, my, bx[N], by[N];
      8 ll res;
      9 struct Rec
     10 {
     11     int x[2], y[2]; 
     12     void scan()
     13     {
     14         for (int i = 0; i < 2; ++i) scanf("%d%d", x + i, y + i);
     15         if (x[0] > x[1]) swap(x[0], x[1]);
     16         if (y[0] > y[1]) swap(y[0], y[1]);
     17         bx[++mx] = x[0];
     18         bx[++mx] = x[1];
     19         by[++my] = y[0];
     20         by[++my] = y[1]; 
     21     }
     22 }rec[N];
     23 vector <pii> v[N];  
     24 
     25 void Hash()
     26 {
     27     sort(bx + 1, bx + 1 + mx);
     28     sort(by + 1, by + 1 + my);
     29     mx = unique(bx + 1, bx + 1 + mx) - bx - 1;
     30     my = unique(by + 1, by + 1 + my) - by - 1;
     31     for (int i = 1; i <= n; ++i) 
     32     {
     33         for (int j = 0; j < 2; ++j)
     34         {
     35             rec[i].x[j] = lower_bound(bx + 1, bx + 1 + mx, rec[i].x[j]) - bx;
     36             rec[i].y[j] = lower_bound(by + 1, by + 1 + my, rec[i].y[j]) - by; 
     37         }
     38     }
     39 }
     40 
     41 namespace SEG
     42 {
     43     struct node
     44     {
     45         ll sum, val;
     46         int lazy; 
     47         node () {}
     48         node (ll sum, ll val, int lazy) : sum(sum), val(val), lazy(lazy) {}
     49         void init() { sum = val = lazy = 0; }
     50         node operator + (const node &other) const { return node(sum + other.sum, val + other.val, 0); }
     51         void Xor() { val = sum - val; lazy ^= 1; }   
     52     }a[N << 2];
     53     void build(int id, int l, int r)
     54     {
     55         a[id] = node(0, 0, 0);
     56         if (l == r) 
     57         {
     58             a[id].sum = by[l + 1] - by[l];
     59             return;
     60         }
     61         int mid = (l + r) >> 1;
     62         build(id << 1, l, mid);
     63         build(id << 1 | 1, mid + 1, r);
     64         a[id] = a[id << 1] + a[id << 1 | 1];
     65     }
     66     void pushdown(int id)
     67     {
     68         if (!a[id].lazy) return;
     69         a[id << 1].Xor();
     70         a[id << 1 | 1].Xor();
     71         a[id].lazy = 0;
     72     }
     73     void update(int id, int l, int r, int ql, int qr)
     74     {
     75         if (l >= ql && r <= qr) 
     76         {
     77             a[id].Xor();
     78             return;
     79         }
     80         int mid = (l + r) >> 1;
     81         pushdown(id);
     82         if (ql <= mid) update(id << 1, l, mid, ql, qr);
     83         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr);
     84         a[id] = a[id << 1] + a[id << 1 | 1];
     85     }
     86 }
     87 
     88 int main()
     89 {
     90     while (scanf("%d", &n) != EOF)
     91     {
     92         mx = my = 0; res = 0; 
     93         for (int i = 1; i <= 2 * n; ++i) v[i].clear();
     94         for (int i = 1; i <= n; ++i) rec[i].scan(); Hash();    
     95         for (int i = 1; i <= n; ++i) 
     96         {
     97             v[rec[i].x[0]].emplace_back(rec[i].y[0], rec[i].y[1] - 1);
     98             v[rec[i].x[1]].emplace_back(rec[i].y[0], rec[i].y[1] - 1); 
     99         }
    100         n <<= 1;    
    101         SEG::build(1, 1, n);  
    102         for (int i = 1; i < mx; ++i)
    103         {
    104             for (auto it : v[i]) SEG::update(1, 1, n, it.first, it.second);
    105             res += (bx[i + 1] - bx[i]) * SEG::a[1].val;    
    106         }
    107         printf("%lld
    ", res); 
    108     }
    109     return 0;
    110 }
    View Code

    G:Goat on a Rope

    Solved.

    签到。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 double x, y;
     6 double xa, xb, ya, yb;
     7 
     8 double calc(double xa, double ya, double xb, double yb)
     9 {
    10     return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
    11 }
    12 
    13 int main()
    14 {
    15     while(~scanf("%lf %lf %lf %lf %lf %lf", &x, &y, &xa, &ya, &xb, &yb))
    16     {
    17         double ans = 1e9;
    18         if(x >= min(xa, xb) && x <= max(xa, xb)) ans = min(ans, min(fabs(y - ya), fabs(y - yb)));
    19         if(y >= min(ya, yb) && y <= max(ya, yb)) ans = min(ans, min(fabs(x - xa), fabs(x - xb)));
    20         ans = min(ans, calc(x, y, xa, ya));
    21         ans = min(ans, calc(x, y, xa, yb));
    22         ans = min(ans, calc(x, y, xb, ya));
    23         ans = min(ans, calc(x, y, xb, yb));
    24         printf("%.3f
    ", ans);
    25     }
    26     return 0;
    27 }
    View Code

    H:Repeating Goldbachs

    Solved.

    签到。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e6 + 10;
     6 
     7 bool isprime[maxn];
     8 int prime[maxn];
     9 
    10 void Init()
    11 {
    12     memset(isprime, true, sizeof isprime);
    13     isprime[0] = isprime[1] = false;
    14     for(int i = 2; i < maxn; ++i)
    15     {
    16         if(isprime[i])
    17         {
    18             prime[++prime[0]] = i;
    19             for(int j = i * 2; j < maxn; j += i)
    20             {
    21                 isprime[j] = false;
    22             }
    23         }
    24     }
    25 }
    26 
    27 int x;
    28 
    29 int main()
    30 {
    31     Init();
    32     while(~scanf("%d", &x))
    33     {
    34         int ans = 0;
    35         while(x >= 4)
    36         {
    37             for(int i = 1; i <= prime[0]; ++i)
    38             {
    39                 int tmp = prime[i];
    40                 if(isprime[x - tmp])
    41                 {
    42                     ++ans;
    43                     x = x - tmp - tmp;
    44                     break;
    45                 }
    46             }
    47         }
    48         printf("%d
    ", ans);
    49     }
    50     return 0;
    51 }
    View Code

    I:Inversions

    Unsolved.

    题意:

    给出一些序列,一些位置上的数字可以在$[1, k]的范围内随便填,求如果填使得整个序列的逆序对个数最多$

    J:Time Limits

    Solved.

    签到。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n, s;
     6 
     7 int main()
     8 {
     9     while(~scanf("%d %d", &n, &s))
    10     {
    11         int Max = -1;
    12         for(int i = 1; i <= n; ++i)
    13         {
    14             int num;
    15             scanf("%d", &num);
    16             Max = max(Max, num);
    17         }
    18         Max *= s;
    19         int ans = Max / 1000;
    20         if(Max % 1000) ans++;
    21         printf("%d
    ", ans);
    22     }
    23     return 0;
    24 }
    View Code

    K:Knockout

    Unsolved.

    题意:

    给出一个数字,然后两个骰子的点数,每次可以移掉数字当中某几位加起来的和等于两骰子点数之和

    那么就可以移掉这几位,知道最后不能移位置,最后剩下的数就是分数

    现在给出一中间局面,求移掉哪些,使得最后的分数期望最大以及最小

    L:Liars

    Solved.

    签到。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e3 + 10;
     6 
     7 int n;
     8 int cnt[maxn];
     9 
    10 int main()
    11 {
    12     while(~scanf("%d", &n))
    13     {
    14         memset(cnt, 0, sizeof cnt);
    15         for(int i = 1; i <= n; ++i)
    16         {
    17             int ai, bi;
    18             scanf("%d %d", &ai, &bi);
    19             for(int j = ai; j <= bi; ++j)
    20             {
    21                 cnt[j]++;
    22             }
    23         }
    24         int ans = -1;
    25         for(int i = 1; i <= n; ++i)
    26         {
    27             if(cnt[i] == i) ans = i;
    28         }
    29         printf("%d
    ", ans);
    30     }
    31     return 0;
    32 }
    View Code

    M:Mobilization

    Unsolved.

    题意:

    $有m种军队,每种军队有h_i 属性 和 p_i属性,以及购买一支军队需要c_i的钱,每种军队可以购买无限支$

    $现在你有C个单位的钱,求如何购买军队,使得sum h_i cdot sum p_i 最大$

  • 相关阅读:
    Python 集合
    Python sorted()
    CodeForces 508C Anya and Ghosts
    CodeForces 496B Secret Combination
    CodeForces 483B Friends and Presents
    CodeForces 490C Hacking Cypher
    CodeForces 483C Diverse Permutation
    CodeForces 478C Table Decorations
    CodeForces 454C Little Pony and Expected Maximum
    CodeForces 313C Ilya and Matrix
  • 原文地址:https://www.cnblogs.com/Dup4/p/10086500.html
Copyright © 2011-2022 走看看