CodeCraft-19 and Codeforces Round #537 (Div. 2)

 

A. Superhero Transformation

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1010
 5 char s[N], t[N], Hash[N];
 6 
 7 bool ok()
 8 {
 9     int n = strlen(s + 1);
10     for (int i = 1; i <= n; ++i) 
11         if (Hash[s[i]] != Hash[t[i]])
12             return false;
13     return true;
14 }
15 
16 int main()
17 {
18     memset(Hash, 0, sizeof Hash);
19     Hash['a'] = 1;
20     Hash['e'] = 1;
21     Hash['i'] = 1;
22     Hash['o'] = 1;
23     Hash['u'] = 1;
24     while (scanf("%s%s", s + 1, t + 1) != EOF)
25     {
26         int len1 = strlen(s + 1), len2 = strlen(t + 1);
27         if (len1 != len2) puts("No");
28         else
29             puts(ok() ? "Yes" : "No");
30     }
31     return 0;
32 }
View Code

 

B. Average Superhero Gang Power

Hacked.

注意如果最大值不止一个,那么去掉几个是不一定的

枚举即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 int n, k, m;
 7 ll a[N];
 8 
 9 int main()
10 {
11     while (scanf("%d%d%d", &n, &k, &m) != EOF)
12     {
13         for (int i = 1; i <= n; ++i) scanf("%lld", a + i);
14         sort(a + 1, a + 1 + n);
15         for (int i = 1; i <= n; ++i) a[i] += a[i - 1];
16         double res = a[n] * 1.0 / n;
17         for (int i = 0; i < n; ++i)
18         {
19             if (m < i) break;
20             ll add = min(1ll * (m - i), 1ll * k * (n - i));
21             res = max(res, (a[n] - a[i] + add) * 1.0 / (n - i));    
22         }
23         printf("%.10f\n", res); 
24     }
25     return 0;
26 }
View Code

 

C. Creative Snap

递归求解即可,注意一整段空直接返回$A$

这样最多只有$k个长度为1的节点被访问到$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 
 6 int n, k, A, B;
 7 vector <int> v;
 8 
 9 ll CDQ(ll l, ll r)
10 {
11     if (r < l) return 0;
12     int num = upper_bound(v.begin(), v.end(), r) - lower_bound(v.begin(), v.end(), l);
13     if (num == 0) return A;  
14     ll tmp = 1ll * (r - l + 1) * B * num;
15     if (l == r) return tmp; 
16     ll mid = (l + r) >> 1;
17     return min(tmp, CDQ(l, mid) + CDQ(mid + 1, r));  
18 }
19 
20 int main()
21 {
22     while (scanf("%d%d%d%d", &n, &k, &A, &B) != EOF)
23     {
24         v.clear();
25         for (int i = 1, x; i <= k; ++i) 
26         {
27             scanf("%d", &x);
28             v.push_back(x);
29         }
30         sort(v.begin(), v.end());
31         printf("%lld\n", CDQ(1, 1 << n)); 
32     }
33     return 0;
34 }
View Code

 

D. Destroy the Colony

Solved.

题意:

有$n个人,n为偶数, 每个人有一个种类$

$询问给出x, y  要求将和第x人同种类并且和第y个人同种类的人放在一个集合$

$并且挑选出一些人和他们放在一起,剩下的人在另一个集合$

$要求两个集合人数相等,并且同一种类的人属于同个集合$

$给出有多少种分配方式, 集合里是有顺序的,并且两个集合是不同的$ 

思路:

考虑一共有$f种方式将其他人和第x人同种类的人以及第y人同种类的人放在一个集合$

$我们假定 第i种类的人有c_i个, 令m = \frac{n}{2}$

$那么答案就是 \frac {m! \cdot m! \cdot f \cdot 2}{c_1! \cdot c_2! \cdots}$

那么考虑怎么处理$f, 可以用背包,但是暴力预处理时间复杂度是O(52^{3} \cdot n)$

$但是我们可以先处理好总的,注意到对于每种情况的处理只有最多两项物品的删除$

$直接删除方案数即可 这样时间复杂度就是O(52^{2} \cdot n)$

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define ll long long
  5 #define N 100010
  6 const ll MOD = (ll)1e9 + 7;
  7 char s[N];
  8 int cnt[110], Hash[210];
  9 int n, q, x, y, mid;
 10 ll fac[N], inv[N];
 11 ll f[110][110]; 
 12 ll g[N]; 
 13 
 14 ll qmod(ll base, ll n)
 15 {
 16     ll res = 1;
 17     while (n)
 18     {
 19         if (n & 1) res = res * base % MOD;
 20         base = base * base % MOD;
 21         n >>= 1;
 22     }
 23     return res;
 24 }
 25 
 26 ll C(int n, int m)
 27 {
 28     return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
 29 }
 30 
 31 int main()
 32 {
 33     fac[0] = 1;
 34     for (int i = 1; i <= 100000; ++i) fac[i] = (fac[i - 1] * i) % MOD;
 35     inv[100000] = qmod(fac[100000], MOD - 2);
 36     for (int i = 100000; i >= 1; --i) inv[i - 1] = (inv[i] * i) % MOD;
 37     for (int i = 1; i <= 26; ++i) Hash['a' + i - 1] = i;
 38     for (int i = 27; i <= 52; ++i) Hash['A' + i - 27] = i; 
 39     while (scanf("%s", s + 1) != EOF)
 40     {
 41         n = strlen(s + 1);
 42         mid = n / 2;
 43         memset(cnt, 0, sizeof cnt);
 44         for (int i = 1; i <= n; ++i) ++cnt[Hash[s[i]]];
 45         ll tmp = 1; 
 46         for (int i = 1; i <= 52; ++i) 
 47             if (cnt[i]) tmp = (tmp * inv[cnt[i]]) % MOD;
 48         memset(f, 0, sizeof f);
 49         memset(g, 0, sizeof g); 
 50         g[0] = 1;
 51         for (int i = 1; i <= 52; ++i) if (cnt[i])
 52         {
 53             for (int j = mid; j >= cnt[i]; --j)
 54                 g[j] += g[j - cnt[i]];
 55         } 
 56         for (int i = 1; i <= 52; ++i)
 57         {
 58             for (int j = i + 1; j <= 52; ++j)
 59             {
 60                 if (cnt[i] == 0 || cnt[j] == 0) continue;
 61                 if (cnt[i] + cnt[j] > mid) continue;
 62                 if (cnt[i] + cnt[j] == mid)
 63                 {
 64                     f[i][j] = f[j][i] = 1;
 65                     continue;
 66                 }
 67                 for (int k = cnt[i]; k <= mid; ++k)
 68                     g[k] -= g[k - cnt[i]];
 69                 for (int k = cnt[j]; k <= mid; ++k)
 70                     g[k] -= g[k - cnt[j]];
 71                 f[i][j] = f[j][i] = g[mid - cnt[i] - cnt[j]] % MOD;
 72                 //printf("%d %d %lld\n", i, j, f[i][j]);
 73                 for (int k = mid; k >= cnt[i]; --k)
 74                     g[k] += g[k - cnt[i]];
 75                 for (int k = mid; k >= cnt[j]; --k)
 76                     g[k] += g[k - cnt[j]];
 77             }
 78         }
 79         for (int i = 1; i <= 52; ++i) if (cnt[i] && cnt[i] <= mid) 
 80         {
 81             for (int j = cnt[i]; j <= mid; ++j)
 82                 g[j] -= g[j - cnt[i]];
 83             f[i][i] = g[mid - cnt[i]] % MOD;
 84             //printf("%d %lld\n", i, f[i][i]);
 85             //printf("%d %d %lld\n", i, i, f[i][i]);
 86             for (int j = mid; j >= cnt[i]; --j)
 87                 g[j] += g[j - cnt[i]];
 88         }
 89         //for (int i = 1; i <= mid; ++i) printf("%lld%c", g[i], " \n"[i == mid]);
 90         scanf("%d", &q);
 91         while (q--)
 92         {
 93             scanf("%d%d", &x, &y);
 94             //cout << f[Hash[s[x]]][Hash[s[y]]] << endl;
 95             ll res = fac[mid] * fac[mid] % MOD * 2 % MOD * tmp % MOD * f[Hash[s[x]]][Hash[s[y]]] % MOD; 
 96             printf("%lld\n", res);
 97         }
 98     }
 99     return 0;
100 }
View Code

 

 

E. Tree

Upsolved.

题意:

在一棵树上

$每次询问给出一些点,根节点r以及组数m$

$要求将所有点分配到一个组中,最多分成m组,要求同一组的点任意两点不能是祖先关系$

$给出分配方案数$

思路:

考虑假如根节点是$1$

$dp[i][j] 表示到第i个点放进j个集合的方案数$

$首先要将点按DFS序排序 令f[i] 表示 i这个点有多少祖先在这里$

$dp[i][j] = dp[i - 1][j] * (j - f[i]) + dp[i - 1][j - 1]$

 

那么我们再考虑根节点任意的情况

$其实原来多少祖先就是点到1的路径上有多少点出现过$

$那么根节点任意的话 就是当前点到根节点的简单路径有多少点出现过$

$按照这个排序,就可以不重不漏的统计$

$维护节点出现个数 可以用DFS序+BIT 维护$

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define ll long long 
  5 #define N 100010
  6 const ll MOD = (ll)1e9 + 7;
  7 int n, q;
  8 vector <int> G[N];
  9 int f[N], vec[N], mark[N];
 10 ll dp[1010]; 
 11 
 12 int top[N], fa[N], deep[N], sze[N], son[N], lp[N], rp[N], cnt;
 13 void DFS(int u)
 14 {
 15     sze[u] = 1;
 16     for (auto v : G[u]) if (v != fa[u])
 17     {
 18         fa[v] = u;
 19         deep[v] = deep[u] + 1;
 20         DFS(v);
 21         sze[u] += sze[v];
 22         if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 
 23     }
 24 }
 25 
 26 void gettop(int u, int sp)
 27 {
 28     top[u] = sp;
 29     lp[u] = ++cnt;
 30     if (!son[u])
 31     {
 32         rp[u] = cnt;
 33         return;
 34     }
 35     gettop(son[u], sp);
 36     for (auto v : G[u]) if (v != fa[u] && v != son[u])
 37         gettop(v, v);
 38     rp[u] = cnt;
 39 }
 40 
 41 int lca(int u, int v)
 42 {
 43     while (top[u] != top[v])
 44     {
 45         if (deep[top[u]] < deep[top[v]]) swap(u, v);
 46         u = fa[top[u]];
 47     }
 48     if (deep[u] > deep[v]) swap(u, v);
 49     return u;
 50 }
 51 
 52 namespace BIT
 53 {
 54     int a[N];
 55     void init() { memset(a, 0, sizeof a); }
 56     void update(int x, int val)
 57     {
 58         for (; x < N; x += x & -x)
 59             a[x] += val;
 60     }
 61     int query(int x)
 62     {
 63         int res = 0;
 64         for (; x > 0; x -= x & -x)
 65             res += a[x];
 66         return res;
 67     }
 68     void update(int l, int r, int val)
 69     {
 70         update(l, val);
 71         update(r + 1, -val);
 72     }
 73 };
 74 
 75 int main()
 76 {
 77     while (scanf("%d%d", &n, &q) != EOF)
 78     {
 79         for (int i = 1; i <= n; ++i) G[i].clear();
 80         memset(mark, 0, sizeof mark);
 81         memset(son, 0, sizeof son);    
 82         cnt = 0;
 83         BIT::init();
 84         for (int i = 1, u, v; i < n; ++i) 
 85         {
 86             scanf("%d%d", &u, &v);
 87             G[u].push_back(v);
 88             G[v].push_back(u);
 89         }
 90         DFS(1); gettop(1, 1);
 91         int k, m, r;
 92         while (q--)
 93         {
 94             scanf("%d%d%d", &k, &m, &r);
 95             for (int i = 0; i <= m; ++i) dp[i] = 0; dp[0] = 1;
 96             for (int i = 1; i <= k; ++i) 
 97                 scanf("%d", vec + i);
 98             for (int i = 1; i <= k; ++i)
 99             {
100                 int x = vec[i]; 
101                 mark[x] = 1; 
102                 BIT::update(lp[x], rp[x], 1);
103             }
104             int ans_root = BIT::query(lp[r]);
105             for (int i = 1; i <= k; ++i)
106             {
107                 int x = vec[i];
108                 int y = lca(x, r);
109                 f[x] = BIT::query(lp[x]) + ans_root - 2 * BIT::query(lp[y]) + (mark[y] == 1) - 1;
110             }
111             for (int i = 1; i <= k; ++i)
112             {
113                 int x = vec[i];
114                 mark[x] = 0;
115                 BIT::update(lp[x], rp[x], -1);
116             }
117             sort(vec + 1, vec + 1 + k, [](int x, int y) 
118             {
119                 return f[x] < f[y];             
120             });
121             if (f[vec[k]] >= m) puts("0");
122             else
123             {
124                 for (int i = 1; i <= k; ++i)
125                 {
126                     int x = vec[i];
127                     for (int j = min(i, m); j >= 0; --j)
128                     {
129                         if (j <= f[x]) dp[j] = 0;
130                         else
131                             dp[j] = (1ll * dp[j] * (j - f[x]) % MOD + dp[j - 1]) % MOD;
132                     }
133                 }
134                 ll ans = 0;
135                 for (int i = 1; i <= m; ++i) ans = (ans + dp[i]) % MOD;
136                 printf("%lld\n", ans);
137             }    
138         }
139     }
140     return 0;
141 }
View Code

 

posted @ 2019-02-04 08:50  Dup4  阅读(398)  评论(0编辑  收藏  举报