• CCPC-Wannafly Winter Camp Day7 (Div2, onsite)


    Replay


    Dup4:

    • 啥都不会? 只能看着两位聚聚A题?

    X:

    • 模拟题不会写, 日常摔锅
    • u, v分不清, 日常演员
    • 又是自己没理清楚就抢键盘上机导致送了一万个罚时, 日常背锅 

    A:迷宫

    Solved.

    考虑所有人从1号点排队出发,所有人都回到自己位置的时间

    让深度大的先走,这样就不会产生堵塞

    那么每个人的时间就是 在1号点的等待时间+深度

    取最大值即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 int n, a[N];
     6 vector <int> G[N];
     7 
     8 int deep[N], fa[N];
     9 void DFS(int u)
    10 {
    11     for (auto v : G[u]) if (v != fa[u])
    12     {
    13         deep[v] = deep[u] + 1;
    14         fa[v] = u;
    15         DFS(v);
    16     }
    17 }
    18 
    19 int main()
    20 {
    21     while (scanf("%d", &n) != EOF)
    22     {
    23         for (int i = 1; i <= n; ++i) G[i].clear();
    24         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    25         for (int i = 1, u, v; i < n; ++i)
    26         {
    27             scanf("%d%d", &u, &v);
    28             G[u].push_back(v);
    29             G[v].push_back(u);
    30         }
    31         deep[1] = 0; DFS(1);
    32         vector <int> vec;
    33         for (int i = 1; i <= n; ++i) if (a[i]) vec.push_back(i);
    34         sort(vec.begin(), vec.end(), [](int a, int b) { return deep[a] > deep[b]; });
    35         int res = 0;
    36         int cnt = 0;
    37         for (auto it : vec)
    38         {
    39             res = max(res, cnt + deep[it]);
    40             ++cnt;
    41         }
    42         printf("%d
    ", res);
    43     }
    44     return 0;
    45 }
    View Code

    C:斐波那契数列

    Solved.

    斐波那契数列$前n项和的通项是$

    $Fib_n & (Fib_n - 1) = Fib_n - lowbit(Fib_n)$

    $S_n = 2 cdot a_n + a_{n - 1} - 1$

    打表找规律发现

    后面那部分是

    $1 1 2 1 1 8 1 1 2 1 1 16 1 1 2 1 1 8 1 1 2 1 1cdots$

    有对称性,可以递归求和

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 const ll MOD = (ll)998244353;
      6 
      7 int t; ll R;
      8 struct node
      9 {
     10     ll a[2][2];
     11     node operator * (const node &other) const
     12     {
     13         node res; memset(res.a, 0, sizeof res.a);
     14         for (int i = 0; i < 2; ++i) 
     15             for (int j = 0; j < 2; ++j)
     16                 for (int k = 0; k < 2; ++k)
     17                     res.a[i][j] = (res.a[i][j] + a[i][k] * other.a[k][j] % MOD + MOD) % MOD;
     18         return res;
     19     }
     20 };
     21 
     22 ll a[2][2] = 
     23 {
     24     1, 1,
     25     1, 0,
     26 };
     27 
     28 ll b[2][2] = 
     29 {
     30     1, 1,
     31     0, 0, 
     32 };
     33 
     34 node qpow(ll n)
     35 {
     36     node base;
     37     for (int i = 0; i < 2; ++i) 
     38         for (int j = 0; j < 2; ++j)
     39             base.a[i][j] = a[i][j];
     40     node res;
     41     for (int i = 0; i < 2; ++i)
     42         for (int j = 0; j < 2; ++j)
     43             res.a[i][j] = b[i][j];
     44     while (n)
     45     {
     46         if (n & 1) res = res * base;
     47         base = base * base;
     48         n >>= 1;
     49     }
     50     return res;
     51 }
     52 
     53 ll qpow(ll base, ll n)
     54 {
     55     ll res = 1;
     56     while (n)
     57     {
     58         if (n & 1) res = (res * base) % MOD;
     59         base = (base * base) % MOD;
     60         n >>= 1;
     61     }
     62     return res;
     63 }
     64 
     65 
     66 ll pos[64], num[64], sum[64];
     67 ll solve(ll now)
     68 {
     69     if (now <= 0) return 0; 
     70     if (now == 1) return 1;
     71     if (now == 2) return 2;
     72     if (now == 3) return 4;
     73     if (now == 4) return 5;
     74     if (now == 5) return 6;
     75     int id = upper_bound(pos + 1, pos + 62, now) - pos - 1; 
     76     if (pos[id] == now) return (sum[id] + num[id]) % MOD; 
     77     return ((solve(now - pos[id]) + solve(pos[id])) % MOD);  
     78 }
     79 
     80 int main()
     81 {
     82     pos[1] = 6;
     83     for (int i = 2; i <= 61; ++i) pos[i] = pos[i - 1] << 1; 
     84     num[1] = 8;
     85     for (int i = 2; i <= 61; ++i) num[i] = (num[i - 1] << 1) % MOD;
     86     sum[1] = 6;
     87     for (int i = 2; i <= 61; ++i) sum[i] = ((sum[i - 1] << 1) % MOD + num[i - 1]) % MOD;
     88     scanf("%d", &t);
     89     while (t--)
     90     {
     91         scanf("%lld", &R);
     92         ll need = 0;
     93         if (R == 1) need = 1;
     94         else if (R == 2) need = 2;
     95         else if (R == 3) need = 4;
     96         else need = (2ll * qpow(R - 2).a[0][0] % MOD + qpow(R - 3).a[0][0] % MOD - 1 + MOD) % MOD;
     97         //cout << R << " " << need << " " << solve(R) << "
    ";
     98         printf("%lld
    ", (need - solve(R) % MOD + MOD) % MOD);  
     99     }
    100     return 0;
    101 }
    View Code

      

    D:二次函数

    Solved.

    枚举哪两个式子相等,做三次

    考虑二元一次方程的根,令$y相同,则有$

    $x_1 = -frac{a_1 pm sqrt{4 cdot y + a_1^2 - 4 cdot b_1}}{2}$

    $x_2 = -frac{a_2 pm sqrt{4 cdot y + a_2^2 - 4 cdot b_2}}{2}$

    考虑根号下一定是一个平方数

    那么令$T^2 = 4 cdot y + a_1^2 - 4 cdot b_1$

    $t^2 = 4 cdot y + a_2^2 - 4 cdot b_2$

    $T^2 - t^2 = (T + t) cdot (T - t) = a_1^2 - 4 cdot b_1 - a_2^2 + 4 cdot b_2$

    $枚举差值的因数分解,得到T 和 t 再判断是否可以$

    $再特判 差值为0 和 差值为1的情况$ 

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define pll pair <ll, ll>
     6 int t;
     7 ll a[3], b[3];
     8 
     9 pll res;
    10 bool solve(ll a1, ll b1, ll a2, ll b2)
    11 {
    12     ll t1 = (a1 * a1 - 4 * b1);
    13     ll t2 = (a2 * a2 - 4 * b2);
    14     ll gap = abs(t1 - t2);
    15     if (gap == 0)
    16     {
    17         if ((t1 & 1) == (t2 & 1))
    18         {
    19             res.first = 0;
    20             res.second = -(a2 - a1) / 2;
    21             return true;
    22         }
    23         else
    24             return false;
    25     }
    26     if (gap == 1)
    27     {
    28         if ((t1 & 1) != (t2 & 1))
    29         {
    30             if (t1 > t2 && ((a1 & 1) == 1))
    31             {
    32                 res.first = -(a1 + 1) / 2;
    33                 res.second = -a2 / 2;
    34                 return true;
    35             }
    36             else if (t1 < t2 && ((a2 & 1) == 1))
    37             {
    38                 res.first = -a1 / 2;
    39                 res.second = -(a2 + 1) / 2;
    40                 return true;
    41             }
    42             else return false;
    43         }
    44     }
    45     for (int i = 1; i * i < gap; ++i) if (gap % i == 0 && (i + gap / i) % 2 == 0)
    46     {
    47         ll T = (i + gap / i) / 2;
    48         ll t = (gap / i - i) / 2;
    49         if (t1 < t2) swap(T, t);
    50         if ((T + a1) % 2 == 0 && (t + a2) % 2 == 0)
    51         {
    52             res.first = -((T + a1) / 2);
    53             res.second = -((t + a2) / 2);
    54             return true;
    55         }
    56     }
    57     return false;
    58 }
    59 
    60 void work()
    61 {
    62     for (int i = 0; i < 3; ++i)
    63         for (int j = i + 1; j < 3; ++j)
    64         {
    65             if (solve(a[i], b[i], a[j], b[j]))
    66             {
    67                 if (i == 0)
    68                 {
    69                     printf("%lld %lld %lld
    ", res.first, j == 1 ? res.second : 0, j == 1 ? 0 : res.second);
    70                 }
    71                 else
    72                     printf("0 %lld %lld
    ", res.first, res.second);
    73                 return;
    74             }
    75         }
    76 }
    77 
    78 int main()
    79 {
    80     scanf("%d", &t);
    81     while (t--)
    82     {
    83         for (int i = 0; i < 3; ++i) scanf("%lld%lld", a + i, b + i);
    84         work();    
    85     }
    86     return 0;
    87 }
    View Code

    E:线性探查法

    Solved.

    拓扑排序?

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int MAXN = 1e6 + 10;
     6 const int maxn = 1e3 + 10;
     7 
     8 struct Edge{
     9     int to, nxt;
    10     Edge(){}
    11     Edge(int to, int nxt): to(to), nxt(nxt){}
    12 }edge[MAXN << 1];
    13 
    14 struct node{
    15     int val;
    16     int index;
    17     node(){}
    18     node(int val, int index):val(val), index(index){}
    19     bool operator < (const node &other) const{
    20         return val > other.val;
    21     }
    22 }brr[maxn];
    23 
    24 int n;
    25 int arr[maxn];
    26 int head[maxn], tot;
    27 int du[maxn];
    28 
    29 void Init()
    30 {
    31     tot = 0;
    32     memset(head, -1, sizeof head);
    33     memset(du, 0, sizeof du);
    34 }
    35 
    36 void addedge(int u,int v)
    37 {
    38     edge[tot] = Edge(v, head[u]); head[u] = tot++;
    39 }
    40 
    41 void solve()
    42 {
    43     priority_queue<node>q;
    44     for(int i = 0; i < n; ++i) if(du[i] == 0)
    45     {
    46         q.push(brr[i]);
    47     }
    48     int tot = 1;
    49     while(!q.empty())
    50     {
    51         node st = q.top();
    52         q.pop();
    53         arr[tot++] = st.val;
    54         int u = st.index;
    55         for(int i = head[u]; ~i; i = edge[i].nxt)
    56         {
    57             int v = edge[i].to;
    58             --du[v];
    59             if(du[v] == 0) q.push(brr[v]);
    60         }
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     while(~scanf("%d" ,&n))
    67     {
    68         Init();
    69         for(int i = 0; i < n; ++i)
    70         {
    71             int x;
    72             scanf("%d", &x);
    73             int now = i;
    74             int pre = x % n;
    75             brr[i] = node(x, i);
    76             while(now != pre)
    77             {
    78                 now = (now - 1 + n) % n;
    79                 addedge(now, i);
    80                 du[i]++;
    81             }
    82         }
    83         solve();
    84         for(int i = 1; i <= n; ++i) printf("%d%c", arr[i], " 
    "[i == n]);
    85     }    
    86     return 0;
    87 }
    View Code

    F:逆序对!

    Solved.

    考虑两个位置的数对有多少个数异或会让他们对答案产生贡献

    如果$a > b 那么从高位到地位找到第一位不同的数 这一位要放0,其他位任意的比m小的数$

    $a < b 同理$

    复杂度$O(n^2logn)$

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

    G:抢红包机器人

    Solved.

    至少存在一个机器人,枚举这一位机器人

    那么它前面所有账号都是机器人,并且这种关系是传递的,DFS即可

    u, v 傻傻分不清楚可还行

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int INF = 0x3f3f3f3f;
     6 
     7 const int MAXN = 1e6 + 10;
     8 const int maxn = 1e2 + 10;
     9 
    10 struct Edge{
    11     int to, nxt;
    12     Edge(){}
    13     Edge(int to, int nxt):to(to), nxt(nxt){}
    14 }edge[MAXN << 1];
    15 
    16 int n, m;
    17 int head[maxn], tot;
    18 int vis[maxn];
    19 int arr[maxn];
    20 
    21 void Init()
    22 {
    23     tot = 0;
    24     memset(head, -1, sizeof head);
    25 }
    26 
    27 void addedge(int u,int v)
    28 {
    29     edge[tot] = Edge(v, head[u]); head[u] = tot++;
    30 }
    31 
    32 void DFS(int u)
    33 {
    34     for(int i = head[u]; ~i; i = edge[i].nxt)
    35     {
    36         int v = edge[i].to;
    37         if(vis[v]) continue;
    38         vis[v] = 1;
    39         DFS(v);
    40     }
    41 }
    42 
    43 int main()
    44 {
    45     while(~scanf("%d %d", &n, &m))
    46     {
    47         Init();
    48         for(int i = 1, k; i <= m; ++i)
    49         {
    50             scanf("%d", &k);
    51             for(int j = 1; j <= k; ++j)
    52             {
    53                 scanf("%d", arr + j);
    54             }
    55             for(int u = k; u >= 1; --u)
    56             {
    57                 for(int v = u - 1; v >= 1; --v)
    58                 {
    59                     addedge(arr[u], arr[v]);
    60                 }
    61             }
    62         }
    63         int ans = INF;
    64         for(int i = 1; i <= n; ++i)
    65         {
    66             memset(vis, 0, sizeof vis);
    67             vis[i] = 1;
    68             DFS(i);
    69             int sum = 0;
    70             for(int j = 1; j <= n; ++j) sum += vis[j];
    71             ans = min(ans, sum);
    72         }
    73         printf("%d
    ", ans);
    74     }
    75     return 0;
    76 }
    View Code

    J:强壮的排列

    Solved.

    打了个表? Comet OJ 支持512Kb  感人

  • 相关阅读:
    MTK Sensor越界导致的系统重启问题分析报告
    WebView兼容问题分析报告
    图片格式问题分析报告
    堆内存double free问题分析报告
    Virsualizer模块野指针问题分析报告
    libjohn hook问题分析报告
    [开发技巧]·Numpy广播机制的深入理解与应用
    [深度应用]·使用一维卷积神经网络处理时间序列数据
    [开发技巧]·Numpy中对axis的理解与应用
    [开发技巧]·HTML检测输入已完成自动填写下一个内容
  • 原文地址:https://www.cnblogs.com/Dup4/p/10324687.html
Copyright © 2020-2023  润新知