• 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", res);
    47     }
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    python基础(5)
    python基础(4)
    python基础(3)
    python基础(2)
    第一个python程序(2)
    第一个python教程(1)
    【jQuery】
    【JavaScript】
    【练习】HTML+CSS
    【练习】Html
  • 原文地址:https://www.cnblogs.com/Dup4/p/10392296.html
Copyright © 2020-2023  润新知