• 2018 Multi-University Training Contest 10 Solution


    A - Problem A.Alkane

    留坑。

    B - Problem B. Beads

    留坑。

    C - Problem C. Calculate

    留坑。

    D - Problem D. Permutation

    留坑。

    E - Problem E. TeaTree

    题意:每个点会存下任意两个以他为LCA的点对的GCD,求每个点存的GCD的最大值

    思路:DSU on tree  用 set 维护子树中的因子,对于重儿子不要处理多次 每次查找的时候,枚举轻儿子中的因子

    还有一种线段树合并的写法

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 100010
      5 
      6 int n;
      7 vector <int> G[N], num[N];
      8 set <int> s;  
      9 int sz[N], son[N], cnt[N], cnt2[N], arr[N], ans[N], Max;
     10 bool isbig[N];  
     11 
     12 void Init()
     13 {
     14     for (int i = 1; i <= 100000; ++i)
     15     {
     16         int limit = sqrt(i); 
     17         for (int j = 1; j < limit; ++j) if (i % j == 0)
     18         {
     19             num[i].push_back(j);
     20             num[i].push_back(i / j);
     21         }
     22         if (i % limit == 0) 
     23         {
     24             num[i].push_back(limit);
     25             if (limit * limit != i) num[i].push_back(i / limit); 
     26         } 
     27     }
     28 }
     29 
     30 void DFS(int u)
     31 {
     32     sz[u] = 1; 
     33     for (auto v : G[u]) 
     34     {
     35         DFS(v); sz[u] += sz[v]; 
     36         if (son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v; 
     37     } 
     38 }
     39 
     40 void update(int u)  
     41 {
     42     for (auto it : num[arr[u]]) ++cnt[it];  
     43     for (auto v : G[u]) if (!isbig[v]) update(v);  
     44 }
     45 
     46 void work(int u, int fa)
     47 {
     48     for (auto it : num[arr[u]]) s.insert(it);
     49     for (auto v : G[u]) if (!isbig[v]) work(v, fa); 
     50 } 
     51 
     52 void query(int u)
     53 {
     54     for (auto v : G[u]) if (!isbig[v]) 
     55     {
     56         s.clear(); 
     57         work(v, u);
     58         for (auto it : s) if (cnt[it] >= 1 || cnt2[it] >= 1) Max = max(Max, it);
     59         for (auto it : s) ++cnt2[it];
     60     } 
     61     for (auto it : num[arr[u]]) if (cnt[it] >= 1 || cnt2[it] >= 1) Max = max(Max, it); 
     62 } 
     63 
     64 void clear(int u)
     65 {
     66     for (auto it : num[arr[u]]) cnt[it] = cnt2[it] = 0;
     67     for (auto v : G[u]) clear(v);
     68 }
     69  
     70 void DSU(int u)
     71 { 
     72     for (auto v : G[u]) if (v != son[u]) DSU(v); 
     73     if (son[u] != -1) { isbig[son[u]] = 1; DSU(son[u]); }
     74     Max = -1; query(u); 
     75     ans[u] = Max;   
     76     if (isbig[u]) update(u);  
     77     if (son[u] != -1) isbig[son[u]] = 0; 
     78     if (!isbig[u]) clear(u);   
     79 }
     80 
     81 int main()
     82 {
     83     Init();
     84     while (scanf("%d", &n) != EOF)
     85     {
     86         for (int i = 1; i <= n; ++i) G[i].clear(); 
     87         memset(son, -1, sizeof son);
     88         memset(cnt, 0, sizeof cnt);
     89         memset(cnt2, 0, sizeof cnt2);
     90         Max = -1; s.clear();
     91         for (int i = 2, u; i <= n; ++i)
     92         {
     93             scanf("%d", &u);
     94             G[u].push_back(i);
     95         }
     96         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
     97         DFS(1); DSU(1);
     98         for (int i = 1; i <= n; ++i) printf("%d
    ", ans[i]);
     99     }
    100     return 0;
    101 }
    View Code
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 vector <int> num[N], G[N];
     6 
     7 int n;
     8 int arr[N], rt[N], ans[N];
     9 
    10 void Init()
    11 {
    12     for (int i = 1; i <= 100000; ++i) for (int j = i; j <= 100000; j += i)
    13         num[j].push_back(i);
    14 }
    15 
    16 struct SEG
    17 {
    18     #define M N * 400
    19     int lson[M], rson[M], c[M], cnt; 
    20     void init() { cnt = 0; }
    21     void pushup(int id) { c[id] = max(c[lson[id]], c[rson[id]]); }
    22     void update(int &x, int l, int r, int pos)
    23     {
    24         if (!x) x = ++cnt;
    25         if (l == r) { c[x] = pos; return; }
    26         int mid = (l + r) >> 1;
    27         pos <= mid ? update(lson[x], l, mid, pos) : update(rson[x], mid + 1, r, pos);
    28         pushup(x);
    29     }
    30     int merge(int u, int v, int &sum)
    31     {
    32         if (!u || !v) return u | v;
    33         if (c[u] == c[v]) sum = max(sum, c[u]); 
    34         if (lson[u] | lson[v]) lson[u] = merge(lson[u], lson[v], sum);
    35         if (rson[u] | rson[v]) rson[u] = merge(rson[u], rson[v], sum);  
    36         return u;
    37     }
    38 }seg;
    39 
    40 void DFS(int u)
    41 {
    42     ans[u] = -1;
    43     for (auto v : G[u])
    44     {
    45         DFS(v);
    46         seg.merge(rt[u], rt[v], ans[u]); 
    47     }
    48 }
    49 
    50 void Run()
    51 {
    52     Init();
    53     while (scanf("%d", &n) != EOF)
    54     {
    55         seg.init();
    56         for (int i = 2, u; i <= n; ++i)
    57         {
    58             scanf("%d", &u);
    59             G[u].push_back(i);
    60         }
    61         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
    62         for (int i = 1; i <= n; ++i) for (auto it : num[arr[i]]) seg.update(rt[i], 1, 100000, it);  
    63         DFS(1);
    64         for (int i = 1; i <= n; ++i) printf("%d
    ", ans[i]);
    65     }
    66 }
    67 
    68 int main()
    69 {
    70     #ifdef LOCAL
    71         freopen("Test.in", "r", stdin);
    72     #endif 
    73 
    74     Run();
    75     return 0;
    76 
    77 }
    View Code

    F - Problem F. NewNippori

    留坑。

    G - Problem G. Cyclic

    打表找规律即可

    $F[n] = (n - 2) * F[n - 1] + (n - 1) * F[n - 2] + (i & 1 ? 1 : -1)$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 #define ll long long
     6 
     7 const ll MOD = 998244353;
     8 
     9 ll arr[N];
    10 
    11 int main()
    12 {
    13     arr[4] = 1, arr[5] = 8;
    14     for (int i = 6; i <= 100000; ++i) arr[i] = ((i - 2) * arr[i - 1] % MOD + (i - 1) * arr[i - 2] % MOD + ((i & 1) ? 1 : -1) + MOD) % MOD;
    15     int t; scanf("%d", &t);
    16     while (t--)
    17     {
    18         int n;
    19         scanf("%d", &n);
    20         printf("%lld
    ", arr[n]);
    21     }
    22 }
    View Code

    H - Problem H. Pow

    水。

    import java.util.Scanner;
    import java.math.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            int t = in.nextInt();
            while (t-- != 0)
            {
                int n = in.nextInt();
                System.out.println(BigInteger.valueOf(2).pow(n));
            }
        }
    }
    View Code

    I - Problem I. Count

    题意:求$sum_{i = 1} ^ {i = n} sum_{j = 1} ^ {j = i - 1} [gcd(i + j, i - j) == 1]$

    思路:找规律。如果是奇数就加上$frac {varphi(n)}{2}   否则加上 varphi(n)$

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int MAXN = 20000000;
     7 bool check[MAXN + 10];
     8 
     9 ll ans[MAXN + 10];
    10 int phi[MAXN + 10];
    11 int prime[MAXN + 10];
    12 int tot;
    13 
    14 void phi_ans_prime_table() {
    15     memset(check, false, sizeof check);
    16     phi[1] = 1;
    17     tot = 0;
    18     for(int i = 2; i <= MAXN; ++i)
    19     {
    20         if(!check[i])
    21         {
    22             prime[tot++] = i;
    23             phi[i] = 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                 phi[i * prime[j]] = phi[i] * prime[j];
    32                 break;
    33             }
    34             else
    35             {
    36                 phi[i * prime[j]] = phi[i] * (prime[j] - 1);
    37             }
    38         }
    39         if(i & 1) ans[i] = ans[i - 1] + phi[i] / 2;
    40         else ans[i] = ans[i - 1] + phi[i];
    41     }
    42 }
    43 
    44 int main() {
    45     phi_ans_prime_table();
    46     int t;
    47     scanf("%d", &t);
    48     while(t--)
    49     {
    50         int n;
    51         scanf("%d", &n);
    52         printf("%lld
    ", ans[n]);
    53     }    
    54     return 0;
    55 }
    View Code

    J - Problem J. CSGO

    题意:有n把主武器和m把副武器,每把武器有k种属性,选取一把主武器和副武器,求题中式子最大值

    思路:对于没种属性又有加减两种状态,枚举每把武器的每种属性的加减状态,求最大值

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
     8 const int maxn = 1e5 + 10;
     9 
    10 ll arr[maxn][10], brr[maxn][10];
    11 ll crr[maxn];
    12 
    13 int n, m, k;
    14 
    15 void RUN()
    16 {
    17     int t;
    18     scanf("%d", &t);
    19     while (t--)
    20     {
    21         scanf("%d %d %d", &n, &m, &k);
    22         for (int i = 1; i <= n; ++i) for (int j = 0; j <= k; ++j) scanf("%lld", &arr[i][j]);
    23         for (int i = 1; i <= m; ++i) for (int j = 0; j <= k; ++j) scanf("%lld", &brr[i][j]);
    24         memset(crr, 0, sizeof crr);
    25         ll ans = 0;
    26         int limit = (1 << k);
    27         for (int i = 1; i <= n; ++i)
    28         {
    29             for (int S = 0; S < limit; ++S)
    30             {
    31                 ll tmp = arr[i][0];
    32                 for (int j = 0; j < k; ++j)
    33                 {
    34                     if (S & (1 << j))
    35                     {
    36                         tmp += arr[i][j + 1];
    37                     }
    38                     else
    39                     {
    40                         tmp -= arr[i][j + 1];
    41                     }
    42                 }
    43                 crr[S] = max(crr[S], tmp);
    44             }
    45         }
    46 
    47         for (int i = 1; i <= m; ++i)
    48         {
    49             for (int S = 0; S < limit; ++S)
    50             {
    51                 ll tmp = brr[i][0];
    52                 for (int j = 0; j < k; ++j)
    53                 {
    54                     if (S & (1 << j))
    55                     {
    56                         tmp += brr[i][j + 1];
    57                     }
    58                     else
    59                     {
    60                         tmp -= brr[i][j + 1];
    61                     }
    62                 }
    63                 ans = max(ans, tmp + crr[limit - 1 - S]);
    64             }
    65         }
    66         printf("%lld
    ", ans);
    67     }
    68 }
    69 
    70 int main()
    71 {
    72 #ifdef LOCAL_JUDGE
    73     freopen("Text.txt", "r", stdin);
    74 #endif // LOCAL_JUDGE
    75 
    76     RUN();
    77 
    78 #ifdef LOCAL_JUDGE
    79     fclose(stdin);
    80 #endif // LOCAL_JUDGE
    81     return 0;
    82 }
    View Code
    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 100010
    #define ll long long
    #define INF 0x3f3f3f3f3f3f3f3f
    
    int t, n, m, K;
    
    struct node
    {
        int x[10];
        void scan(int vis)
        {
            scanf("%d", x + vis);
            for (int i = 2; i <= K + 1; ++i) scanf("%d", x + i); 
        }
    }a[N], b[N];
    
    void Run()
    {
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d%d%d", &n, &m, &K);
            for (int i = 1; i <= n; ++i) a[i].scan(0);
            for (int i = 1; i <= m; ++i) b[i].scan(1);
            ll res = 0;
            for (int i = 0; i < (1 << (K + 2)); ++i) 
            {
                bitset <7> bit; bit = i;
                ll Max[2] = { -INF, -INF };
                ll Min[2] = { INF, INF };
                for (int j = 1; j <= n; ++j)
                {
                    ll tmp = 0;
                    for (int k = 0; k <= K + 1; ++k)
                        tmp += a[j].x[k] * (bit[k] ? 1 : -1);
                    Max[0] = max(Max[0], tmp);
                    Min[0] = min(Min[0], tmp);
                }
                for (int j = 1; j <= m; ++j)
                {
                    ll tmp = 0;
                    for (int k = 0; k <= K + 1; ++k)
                        tmp += b[j].x[k] * (bit[k] ? 1 : -1); 
                    Max[1] = max(Max[1], tmp);
                    Min[1] = min(Min[1], tmp); 
                } 
                res = max(res, max(Max[0] - Min[1], Max[1] - Min[0]));
            }
            printf("%lld
    ", res);
        }
    }
    
    int main()
    {
        #ifdef LOCAL
            freopen("Test.in", "r", stdin); 
        #endif 
    
        Run();
        return 0;
    
    }
    View Code

    K - Problem K. Pow2

    留坑。

    L - Problem L.Videos

    题意:每天有n个小时,有m部电影,k个人,每部电影只能被一个人看,得到w快乐值,电影种类有AB两种,同一人连着看同种电影要减去W快乐值,如何安排使得快乐值最大

    思路:将一部电影拆成两个点 S 和 T 流为1,费用为-w, 电影与电影之间如果是可以连着看的,就连边,如果是同种类,费用就是W, 否则就是0,流为1,源点练出来加一个点,流量为k,限制为k个人

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int INF = 0x3f3f3f3f;
      6 const int maxn = 1e4 + 10;
      7 const int maxm = 1e5 + 10;
      8 
      9 struct Edge{
     10     int to, nxt, cap, flow, cost;
     11 }edge[maxm];
     12 
     13 int head[maxn], tot;
     14 int pre[maxn], dis[maxn];
     15 bool vis[maxn];
     16 int N;
     17 
     18 void Init(int n)
     19 {
     20     N = n;
     21     tot = 0;
     22     for(int i = 0; i < n; ++i) head[i] = -1;
     23 }
     24 
     25 void addedge(int u, int v, int cap, int cost)
     26 {
     27     edge[tot].to = v;
     28     edge[tot].cap = cap;
     29     edge[tot].cost = cost;
     30     edge[tot].flow = 0;
     31     edge[tot].nxt = head[u];
     32     head[u] = tot++;
     33 
     34     edge[tot].to = u;
     35     edge[tot].cap = 0;
     36     edge[tot].cost = -cost;
     37     edge[tot].flow = 0;
     38     edge[tot].nxt = head[v];
     39     head[v] = tot++;
     40 }
     41 
     42 bool SPFA(int s,int t)
     43 {
     44     queue<int>q;
     45     for(int i = 0; i < N; ++i) dis[i] = INF, pre[i] = -1, vis[i] = false;
     46     dis[s] = 0;
     47     vis[s] = true;
     48     q.push(s);
     49     while(!q.empty())
     50     {
     51         int u = q.front();
     52         q.pop();
     53         vis[u] = false;
     54         for(int i = head[u]; ~i; i = edge[i].nxt)
     55         {
     56             int v = edge[i].to;
     57             if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)
     58             {
     59                 dis[v] = dis[u] + edge[i].cost;
     60                 pre[v] = i;
     61                 if(!vis[v])
     62                 {
     63                     vis[v] = true;
     64                     q.push(v);
     65                 }
     66             }
     67         }
     68     }
     69     if(pre[t] == -1) return false;
     70     else return true;
     71 }
     72 
     73 int minCostMaxflow(int s,int t, int &cost)
     74 {
     75     int flow = 0;
     76     cost = 0;
     77     while(SPFA(s, t))
     78     {
     79         int Min = INF;    
     80         for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to])
     81         {
     82             if(Min > edge[i].cap - edge[i].flow)
     83             {
     84                 Min = edge[i].cap - edge[i].flow;
     85             }
     86         }
     87         for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to])
     88         {
     89             edge[i].flow += Min;
     90             edge[i ^ 1].flow -= Min;
     91             cost += edge[i].cost * Min;
     92         }
     93         flow += Min;
     94     }
     95     return flow;
     96 }
     97 
     98 struct node{
     99     int si, ti, wi, op;
    100 }arr[maxn];
    101 
    102 int n, m, K, W;
    103 
    104 int main()
    105 {
    106     int t;
    107     scanf("%d", &t);
    108     while(t--)
    109     {
    110         scanf("%d %d %d %d", &n, &m, &K, &W);
    111         for(int i = 1; i <= m; ++i) scanf("%d %d %d %d", &arr[i].si, &arr[i].ti, &arr[i].wi, &arr[i].op);
    112         Init(2 * m + 3);
    113         addedge(0, 2 * m + 1, K, 0);
    114         for(int i = 1; i <= m; ++i) addedge(2 * m + 1, 2 * i - 1, 1, 0);
    115         for(int i = 1; i <= m; ++i) addedge(2 * i - 1, 2 * i, 1, -arr[i].wi);
    116         for(int i = 1; i <= m; ++i) addedge(2 * i, 2 * m + 2, 1, 0);
    117         for(int i = 1; i <= m; ++i)
    118         {
    119             for(int j = 1; j <= m; ++j)
    120             {
    121                 if(i == j) continue;
    122                 if(arr[i].ti <= arr[j].si)
    123                 {
    124                     if(arr[i].op == arr[j].op)
    125                     {
    126                         addedge(2 * i, 2 * j - 1, 1, W);
    127                     }
    128                     else 
    129                     {
    130                         addedge(2 * i, 2 * j - 1, 1, 0);
    131                     }
    132                 }
    133             }
    134         }
    135         int cost = 0;
    136         minCostMaxflow(0, 2 * m + 2, cost);
    137         printf("%d
    ", -cost);
    138     }
    139     return 0;
    140 }
    View Code
  • 相关阅读:
    使用mongodb保存爬取豆瓣电影的数据
    使用scrapy爬取阳光热线问政平台
    使用scrapy爬取手机版斗鱼主播的房间图片及昵称
    使用selenium + chrome爬取中国大学Mooc网的计算机学科的所有课程链接
    使用scrapy爬取腾讯社招,获取所有分页的职位名称及chaolia、类型、人数、工作地点、发布日期超链接
    python2使用bs4爬取腾讯社招
    使用python2爬取百度贴吧指定关键字和分页帖子楼主所发的图片
    提问的智慧
    深刻理解系统架构师和系统分析师定义
    Redis基础数据结构与核心原理
  • 原文地址:https://www.cnblogs.com/Dup4/p/9806476.html
Copyright © 2020-2023  润新知