其他分享
首页 > 其他分享> > 正睿20秋季普转提day2

正睿20秋季普转提day2

作者:互联网

估分:0+80+60+0=140

实际:0+80+30+0=110

T1:

  不会,不知道怎么算他的数学期望

  每个点每次被覆盖的概率是1/size,size是他的子树大小,因为期望有线性性,最后把所有点的概率加起来就是答案。逆元用线性求,不然会超时。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int N = 10000010;
 8 const int mod = 998244353;
 9 
10 int n;
11 int siz[N], pa[N], inv[N];
12 
13 inline int read()
14 {
15     int x = 0, f = 0;
16     char ch = getchar();
17     while (!isdigit(ch)) f = ch == '-', ch = getchar();
18     while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
19     return f ? -x : x;
20 }
21 
22 int main()
23 {
24     n = read();
25     siz[1] = 1;
26     for (int i = 2; i <= n; i++)
27     {
28         siz[i] = 1;
29         pa[i] = read();
30     }
31 
32     inv[1] = 1;
33     for (int i = 2; i <= n; i++)
34     {
35         inv[i] = (long long)(mod - (mod / i)) * inv[mod % i] % mod;
36     }
37     int ans = 0;
38     for (int i = n; i; i--)
39     {
40         ans = (long long)(ans + inv[siz[i]]) % mod;
41         siz[pa[i]] += siz[i];
42     }
43     printf("%d", ans);
44 }
View Code

 

T2:

  不会,打了80pts暴力

  如果n是偶数就随便拿一个使n变成奇数,当n是奇数时,将糖果按a从大到小排序,先拿掉a最大的糖果,在把剩下的糖果每相邻两个一组,每组选b较大的一个,就是答案。可以容易证明出这样做一定有解。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const int N = 100010;
 9 
10 int n;
11 vector<int> ans;
12 
13 struct Node
14 {
15     int a, b, id;
16     Node() {}
17 };
18 
19 Node s[N];
20 
21 bool cmp(Node a, Node b)
22 {
23     return a.a > b.a;
24 }
25 
26 int main()
27 {
28     scanf("%d", &n);
29     for (int i = 1; i <= n; i++) scanf("%d", &s[i].a);
30     for (int i = 1; i <= n; i++) scanf("%d", &s[i].b), s[i].id = i;
31     sort(s + 1, s + 1 + n, cmp);
32     bool flag = false;
33     if (n % 2 == 0)  ans.push_back(s[n].id), n--, flag = true;
34     ans.push_back(s[1].id);
35     for (int i = 2; i <= n; i+=2)
36     {
37         ans.push_back(s[i].b > s[i + 1].b ? s[i].id : s[i + 1].id);
38     }
39 
40     if (flag) n++;
41     printf("%d\n", n / 2 + 1);
42     for (auto i : ans)
43     {
44         printf("%d ", i);
45     }
46 }
View Code

 

T3:

  不会,打了30pts的暴力和30pts的B=0的情况,然而暴力思路不大对

  二分答案,求出每个节点子树中黑点个数的上限和下限,看是否合法。每个节点的上限为min(子节点的上限和,总节点数-当前节点的B限制),每个节点的下限为max(子节点的下限和,当前节点A限制)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 #define int long long
 8 
 9 const int N = 100010;
10 
11 int n;
12 int k[N];
13 int limA[N], limB[N];
14 int down[N], up[N];
15 int h[N], num[N << 1], nex[N << 1], dqx;
16 
17 void add(int a, int b)
18 {
19     num[dqx] = b;
20     nex[dqx] = h[a];
21     h[a] = dqx++;
22 }
23 
24 void dfs(int u, int fa)
25 {
26     down[u] = 0, up[u] = 1;
27     for (int i = h[u]; ~i; i = nex[i])
28     {
29         int j = num[i];
30         if (j == fa) continue;
31         dfs(j, u);
32         if (down[j] > up[j])
33         {
34             down[u] = 0, up[u] = -1;
35             return;
36         }
37         down[u] += down[j], up[u] += up[j];
38     }
39     down[u] = max(down[u], limA[u]);
40     up[u] = min(up[u], k[u]);
41 }
42 
43 bool check(int x)
44 {
45     for (int i = 1; i <= n; i++)
46     {
47         k[i] = x - limB[i];
48         if (k[i] < limA[i]) return false;
49     }
50 
51     dfs(1, 0);
52     if (down[1] > x || up[1] < x) return false;
53     return true;
54 }
55 
56 signed main()
57 {
58     scanf("%lld", &n);
59     memset(h, -1, sizeof(h));
60     for (int i = 1; i < n; i++)
61     {
62         int a, b;
63         scanf("%lld%lld", &a, &b);
64         add(a, b), add(b, a);
65     }
66 
67     int m;
68 
69     scanf("%lld", &m);
70     for (int i = 1; i <= m; i++)
71     {
72         int x, a;
73         scanf("%lld%lld", &x, &a);
74         limA[x] = max(limA[x], a);
75     }
76 
77     scanf("%lld", &m);
78     for (int i = 1; i <= m; i++)
79     {
80         int x, a;
81         scanf("%lld%lld", &x, &a);
82         limB[x] = max(limB[x], a);
83     }
84 
85     int l = 0, r = n + 1;
86     while (l < r)
87     {
88         int mid = (l + r) >> 1;
89         if (check(mid)) r = mid;
90         else l = mid + 1;
91     }
92 
93     if (r > n) puts("-1");
94     else printf("%lld", r);
95 }
View Code

 

T4:

  不会

  现在依然不会

 

总结:

  关于数论的东西还不熟,数学期望还要回去多看看;第二题是没想到这个思路,光想着排序从大选到小去了;第三题想着计算上下限了,没想着二分答案;第四题是真不会。

  在考场上还是想不到正解,考试经验还是不大足,还得多考多练

  

标签:ch,普转,int,up,down,正睿,20,include,节点
来源: https://www.cnblogs.com/Arrogant-Hierarch/p/13670934.html