Codeforces Round #539 (Div. 2)

A. Sasha and His Trip

签。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, v;
 5 
 6 int main()
 7 {
 8     while (scanf("%d%d", &n, &v) != EOF)
 9     {
10         int res = 0;
11         if (v >= n - 1) res = n - 1;
12         else
13         {
14             res = v;
15             for (int i = 1, j = 2; i <= n - 1 - v; ++i, ++j)
16                 res += j;
17         }
18         printf("%d\n", res);
19     }
20     return 0;
21 }
View Code

 

B. Sasha and Magnetic Machines

签。

如果可以换无限次怎么做?

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 50010
 5 vector <int> fac[110];
 6 int n, a[N], cnt[110];
 7 
 8 int main()
 9 {
10     for (int i = 2; i <= 100; ++i)
11     {
12         fac[i].clear();
13         for (int j = 2; j <= i; ++j) if (i % j == 0)
14             fac[i].push_back(j);
15     }
16     while (scanf("%d", &n) != EOF)
17     {
18         int res = 0;
19         memset(cnt, 0, sizeof cnt);
20         for (int i = 1; i <= n; ++i)
21         {
22             scanf("%d", a + i);
23             res += a[i];
24             ++cnt[a[i]];
25         }
26         int tot = res;
27         for (int i = 1; i <= 100; ++i)
28         {
29             for (int j = 1; j <= 100; ++j) if (cnt[i] && cnt[j] && i != j)
30             {
31                 int tmp = i + j;
32                 for (auto it : fac[i]) 
33                     res = min(res, tot - tmp + i / it + j * it);    
34             }
35         }
36         for (int i = 1; i <= 100; ++i) if (cnt[i] >= 2)
37         {
38             int tmp = 2 * i;
39             for (auto it : fac[i])
40                 res = min(res, tot - tmp + i * it + i / it);
41         }
42         printf("%d\n", res);
43     }
44     return 0;
45 }
View Code

 

C. Sasha and a Bit of Relax

Solved.

题意:

有一个数列,找出多少个$(l, r) 使得 r - l + 1 是偶数 并且$

$a_l \oplus a_{l + 1} \oplus \cdots \oplus a_{mid} = a_{mid +1} \oplus a_{mid +2} \oplus \cdots \oplus a_r$

思路:

令$f[]表示前缀异或$

$那么第二个条件用前缀异或来表示就是 f_r \oplus f_{mid} = f_{mid} \oplus f_{l - 1}$

其实就是统计有多少个$f_r 和 f_{l - 1} 相同,并且 r - l +1 是偶数$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 300010
 6 #define M 1100000
 7 int n, a[N], sum[N];
 8 int cnt[M][2];
 9 
10 ll f(int n)
11 {
12     return 1ll * n * (n - 1) / 2;
13 }
14 
15 int main()
16 {
17     while (scanf("%d", &n) != EOF)
18     {
19         sum[0] = 0;
20         memset(cnt, 0, sizeof cnt);
21         ++cnt[0][0];
22         for (int i = 1; i <= n; ++i) 
23         {
24             scanf("%d", a + i);
25             sum[i] = sum[i - 1] ^ a[i];
26             ++cnt[sum[i]][i & 1]; 
27         }
28         ll res = 0;
29         for (int i = 0; i < (1 << 20); ++i)
30         {
31             res += f(cnt[i][0]) + f(cnt[i][1]);
32         }
33         printf("%lld\n", res);
34     }
35     return 0;
36 }
View Code

 

 

D. Sasha and One More Name

Solved.

题意:

给出一个回文串,可以将该回文串切成若干段再任意拼接

使得拼接之后的串也是回文串并且不是原串

求最小的切割次数

思路:

首先可以考虑一次切割是否可行,可以$O(n^2)判断$

$再考虑二次切割,如果二次切割不行,那么次数再增加都不行$

$二次切割的情况,即将原串一分为二,在左边找一个子串使得这个子串不是回文串$

$那么把这个回文串倒置一下和右边对应位置交换即可$

$首先我们考虑起点都是原串的起点,只需要枚举子串的终点即可$

$因为如果存在某个子串它的起点不是初始起点使得它不是回文,那么将起点移到初始起点,它也不是回文$

$再考虑如果找不到,那么说明所有子串都是回文,这种情况就是所有字符都相等$

$当然如果原串长度是奇数,中间那个字符可以不用考虑$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 5010
 5 char s[N];
 6 int len;
 7 
 8 bool ok(string s)
 9 {
10     int len = s.size();
11     for (int i = 0; i < len / 2; ++i)
12         if (s[i] != s[len - i - 1])
13             return false;
14     return true;
15 }
16 
17 bool same(string str)
18 {
19     for (int i = 0; i < len; ++i)
20         if (str[i] != s[i + 1])
21             return false;
22     return true;
23 }
24 
25 int solve()
26 {
27     len = strlen(s + 1);
28     for (int i = 1; i < len; ++i)
29     {
30         string tmp = "";
31         for (int j = i + 1; j <= len; ++j) tmp += s[j];
32         for (int j = 1; j <= i; ++j) tmp += s[j];
33         if (!same(tmp) && ok(tmp)) return 1;
34     }
35     for (int i = len; i > 1; --i)
36     {
37         string tmp = "";
38         for (int j = i; j <= len; ++j) tmp += s[j];
39         for (int j = 1; j < i; ++j) tmp += s[j];
40         if (!same(tmp) && ok(tmp)) return 1;
41     }
42     string tmp = "";
43     for (int i = 1; i <= len / 2; ++i)
44     {
45         tmp += s[i];
46         if (!ok(tmp)) 
47             return 2;
48     }
49     return -1;
50 }
51 
52 
53 int main()
54 {
55     while (scanf("%s", s + 1) != EOF)
56     {
57         int res = solve();
58         if (res != -1) printf("%d\n", res);
59         else puts("Impossible");
60     }
61     return 0;
62 }
View Code

 

 

F. Sasha and Interesting Fact from Graph Theory

Upsolved.

题意:

要求构造一棵$n$个点的树,使得$a->b的距离为m$

$每条边的边权在[1, m]范围内$

$求生成树个数$

思路:

我们可以枚举$a->b的边数,那么边权的分配就有C_{m - 1}^{edge}$

$并且可以有顺序的选出edge - 1个点是A_{n}^{edge - 1}$

$那么再考虑其他点,剩下的点的个数为n - edge - 1$

$这个点的边的选择都是m种,就是m^{n - edge - 1}$

$再考虑他们构成一棵树,就是有n个点,要分配到k个不同的连通块构成的森林的方案$

$根据Cayley公式f(n, k) = k \cdot n^{n - y - 1}$

$我们要的就是f(n, edge +1)$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 1000010
 6 const ll p = (ll)1e9 + 7;
 7 int n, m, a, b;
 8 ll fac[N], inv[N];
 9 
10 ll qmod(ll base, ll n)
11 {
12     ll res = 1;
13     while (n)
14     {
15         if (n & 1) res = res * base % p;
16         base = base * base % p;
17         n >>= 1;
18     }
19     return res;
20 }
21     
22 ll C(int n, int m)
23 {
24     if (m > n) return 0;
25     return fac[n] * inv[m] % p * inv[n - m] % p;
26 }
27 
28 int main()
29 {
30     fac[0] = 1;
31     for (int i = 1; i <= 1000000; ++i) fac[i] = fac[i - 1] * i % p;
32     inv[1000000] = qmod(fac[1000000], p - 2);
33     for (int i = 1000000; i >= 1; --i) inv[i - 1] = inv[i] * i % p;
34     while (scanf("%d%d%d%d", &n, &m, &a, &b) != EOF)
35     {
36         ll base = 1;
37         ll res = 0;
38         for (int i = n - 2; i >= 0; --i)
39         {
40             base = 1ll * qmod(m, n - 2 - i); 
41             if (n - i - 3 >= 0)
42                 base = base * (i + 2) % p * qmod(n, n - i - 3) % p;
43             res = (res + C(m - 1, i) * C(n - 2, i) % p * base % p * fac[i] % p) % p;
44             //base = base * m % p * (i + 1) % p; 
45         }
46         printf("%lld\n", res);
47     }
48     return 0;
49 }
View Code

 

posted @ 2019-02-17 19:17  Dup4  阅读(237)  评论(0编辑  收藏  举报