• BestCoder Round #85


    5/5

    好久没写博客了,难得有空写个题解,难得有空补不动~~

     

    题A hdu5776 sum

    题意:略

    题解:dp[x]表示前缀modm的余数有没有出现,如果同一个结果出现两次,那么就说明中间的一段是可以整除m的,当然不要忘了本身前缀就能够整除。

     

     1 /*zhen hao*/
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <queue>
     6 #include <vector>
     7 #include <string>
     8 #include <stack>
     9 #include <set>
    10 #include <map>
    11 #include <iostream>
    12 #include <algorithm>
    13 using namespace std;
    14 
    15 #define lson l, m, rt*2
    16 #define rson m + 1, r, rt*2+1
    17 #define xx first
    18 #define yy second
    19 
    20 typedef pair<int,int> pii;
    21 typedef long long ll;
    22 typedef unsigned long long ull;
    23 
    24 const int N = 5e3 + 10;
    25 int dp[N];
    26 
    27 int main() {
    28 //    freopen("case.in", "r", stdin);
    29 
    30     int T;
    31     cin >> T;
    32     while (T--) {
    33         memset(dp, 0, sizeof dp);
    34         int n, m, now = 0, ok = 0;
    35         scanf("%d%d", &n, &m);
    36         for (int i = 0; i < n; i++) {
    37             int x;
    38             scanf("%d", &x);
    39             now = (now + x) % m;
    40             if (now == 0 || dp[now]) ok = 1;
    41             dp[now] = 1;
    42         }
    43         if (ok) puts("YES"); else puts("NO");
    44     }
    45 
    46 }
    代码君

    题B hdu5777 domino

    题意:略

    题解:仔细观察发现贪心可解,sort一下即可。

     

     1 /*zhen hao*/
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <queue>
     6 #include <vector>
     7 #include <string>
     8 #include <stack>
     9 #include <set>
    10 #include <map>
    11 #include <iostream>
    12 #include <algorithm>
    13 using namespace std;
    14 
    15 #define lson l, m, rt*2
    16 #define rson m + 1, r, rt*2+1
    17 #define xx first
    18 #define yy second
    19 
    20 typedef pair<int,int> pii;
    21 typedef long long ll;
    22 typedef unsigned long long ull;
    23 
    24 const int N = 1e5 + 10;
    25 int d[N];
    26 
    27 int main() {
    28 //    freopen("case.in", "r", stdin);
    29 
    30     int T;
    31     cin >> T;
    32     while (T--) {
    33         int n, k;
    34         scanf("%d%d", &n, &k);
    35         for (int i = 0; i < n - 1; i++) {
    36             scanf("%d", d + i);
    37         }
    38         sort(d, d + n - 1, greater<int>());
    39         ll sum = 0;
    40         for (int i = k - 1; i < n - 1; i++) {
    41             sum = sum + d[i];
    42         }
    43         printf("%I64d
    ", sum + n);
    44     }
    45 
    46 }
    代码君

     

    题C hdu5778 abs

    题意:略

    题解:质因子都是2说明这个数一定是平方数,然后对于x,我们先把它去个根的sx,然后我们枚举距离这个sx最近的距离d,然后判断d的质因子是不是都是一个。还有一个问题,我们取得这个sx可能sx+1更优,所以要先判断一下哪个距离x更近。

     

     1 /*zhen hao*/
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <queue>
     6 #include <vector>
     7 #include <string>
     8 #include <stack>
     9 #include <set>
    10 #include <map>
    11 #include <iostream>
    12 #include <algorithm>
    13 using namespace std;
    14 
    15 #define lson l, m, rt*2
    16 #define rson m + 1, r, rt*2+1
    17 #define xx first
    18 #define yy second
    19 
    20 typedef pair<int,int> pii;
    21 typedef long long ll;
    22 typedef unsigned long long ull;
    23 
    24 const int N = 1e5 + 10;
    25 bool vis[N];
    26 vector<int> p;
    27 
    28 void init() {
    29     for (int i = 2; i < N; i++) if (!vis[i])
    30         for (int j = i + i; j < N; j += i) vis[j] = 1;
    31     for (int i = 2; i < N; i++) if (!vis[i]) p.push_back(i);
    32 }
    33 
    34 bool check(ll n) {
    35     if (n < 2) return false;
    36     int m = (int)sqrt(n + 0.5);
    37     for (int i = 0; i < (int)p.size() && p[i] <= m; i++) if (n % p[i] == 0) {
    38         int c = 0;
    39         while (n % p[i] == 0) {
    40             n /= p[i];
    41             c++;
    42         }
    43         if (c > 1) return false;
    44     }
    45     return true;
    46 }
    47 
    48 int main() {
    49 //    freopen("case.in", "r", stdin);
    50 
    51     init();
    52     int T;
    53     cin >> T;
    54     while (T--) {
    55         ll x;
    56         scanf("%I64d", &x);
    57         ll sx = (ll)sqrt(x + 0.5);
    58         if (abs(sx * sx - x) > abs((sx + 1) * (sx + 1) - x)) ++sx;
    59         int d = 0;
    60         while (true) {
    61             if (check(sx + d)) break;
    62             if (check(sx - d)) break;
    63             d++;
    64         }
    65         ll res = 1e18;
    66         if (check(sx + d)) res = min(res, abs(x - (sx + d) * (sx + d)));
    67         if (check(sx - d)) res = min(res, abs(x - (sx - d) * (sx - d)));
    68         cout << res << endl;
    69     }
    70 
    71 }
    代码君

     

    题D 5779 Tower Defence

    题意:略

    题解:太弱了,第一眼看不到题解的状态转移,实际上题解的状态转移描述得已经够专业了。但是我是结合代码才看得懂(/▽╲)!!这里详细地解释一下怎么转移的吧,毕竟都把代码看懂了。

     

    题目说最短路不是k,很容易由反证法得到这个最短路是小于k的。

    先定义一个状态数组,f(i,j,k)表示与1连接的那个连通块(包括1)的size,当前的最短路是j,得到这个最短路的点数是k。

    我们发现如果想要最短路的长度加一,那么必须是从非连通块里面的点连到这k个点的其中x个(1 <= x <= k),所以我们要枚举接下来的连通块以外的新点的个数x,目的是更新状态f(i+x,j+1,x)。

    转移:(假设上一层是k个点,下一层是x个点)

    (1)对于第二层的每个点x,从第一层的k个点里面人选1到k个连边,方法数是2 ^ k - 1。

    (2)对于第二层的每个点x自己互相连边,方案数是2 ^ (x * (x - 1) / 2),因为共有这么条边,可以连也可以不连

    (3)这个最难想,因为我们增加了x个点,那么原来图中有多少个点是可以换位置的呢?答案就是非1和非最短路为j的点,所以由i - k - 1个点里面选x作为最短路为j+1的点。

     

    这三步我们得到了f(i,j,k)。

    给定n和k怎么得到答案呢?枚举与1连通的点,然后剩余的点可以乱排,同样要考虑排列组合。

     

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 #define lson l, m, rt*2
     6 #define rson m + 1, r, rt*2+1
     7 #define xx first
     8 #define yy second
     9 
    10 typedef pair<int,int> pii;
    11 typedef long long ll;
    12 typedef unsigned long long ull;
    13 
    14 const int N = 61, mod = 1e9 + 7;
    15 ll f[N][N][N], C[N][N], p2[N * N], p2_1[N];
    16 
    17 void add(ll& a, ll b) {
    18     a += b;
    19     if (a >= mod) a -= mod;
    20 }
    21 
    22 void init() {
    23     for (int i = 0; i < N; i++) {
    24         C[i][0] = 1;
    25         for (int j = 1; j <= i; j++)
    26             add(C[i][j], (C[i - 1][j] + C[i - 1][j - 1]) % mod);
    27     }
    28 //    cout << C[5][3] << endl;
    29     p2[0] = p2_1[0] = 1;
    30     for (int i = 1; i < N * N; i++) p2[i] = p2[i - 1] * 2 % mod;
    31     for (int i = 1; i < N; i++) p2_1[i] = (p2[i] + mod - 1) % mod;
    32 //    cout << p2[5] << ' ' << p2_1[5] << endl;
    33     f[1][0][1] = 1;
    34     for (int i = 1; i < N; i++)
    35         for (int j = 0; j < i; j++)
    36             for (int k = 1; k <= i; k++) if (f[i][j][k]) {
    37                 ll tmp = f[i][j][k];
    38                 for (int l = 1; l + i < N; l++) {
    39                     tmp = tmp * p2_1[k] % mod;
    40                     ll val = tmp;
    41                     val = val * p2[l * (l - 1) / 2] % mod;
    42                     val = val * C[i + l - 1][l] % mod;
    43                     add(f[i + l][j + 1][l], val);
    44                 }
    45             }
    46 }
    47 
    48 ll get_ans(int n, int k) {
    49     ll ans = 0;
    50     for (int i = 1; i <= n; i++)
    51         for (int j = 0; j < k; j++)
    52             for (int l = 1; l <= i; l++) if (f[i][j][l]) {
    53                 ll tmp = f[i][j][l];
    54                 tmp = tmp * C[n - 1][n - i] % mod;
    55                 tmp = tmp * p2[(n - i) * (n - i - 1) / 2] % mod;
    56                 add(ans, tmp);
    57             }
    58     return ans;
    59 }
    60 
    61 int main() {
    62 //    freopen("case.in", "r", stdin);
    63 
    64     init();
    65     int T;
    66     cin >> T;
    67     while (T--) {
    68         int n, k;
    69         cin >> n >> k;
    70         cout << get_ans(n, k) << '
    ';
    71     }
    72 
    73     return 0;
    74 }
    代码君

     

    题E hdu5780 gcd

    题意:略

    题解:实际上官方题解已经写得很详细了,我再复述有点多余(/▽╲)改天有空补上这个公式证明吧,希望我不会忘记。

     

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 #define lson l, m, rt*2
     6 #define rson m + 1, r, rt*2+1
     7 #define xx first
     8 #define yy second
     9 
    10 typedef pair<int,int> pii;
    11 typedef long long ll;
    12 typedef unsigned long long ull;
    13 
    14 const int N = 1e6, mod = 1e9 + 7;
    15 int phi[N + 10];
    16 ll s[N + 10];
    17 
    18 void phi_table() {
    19     phi[1] = 1;
    20     for (int i = 2; i <= N; i++) if (!phi[i])
    21         for (int j = i; j <= N; j += i) {
    22             if (!phi[j]) phi[j] = j;
    23             phi[j] = phi[j] / i * (i - 1);
    24         }
    25     for (int i = 1; i <= N; i++)
    26         s[i] = (s[i - 1] + phi[i]) % mod;
    27 }
    28 
    29 ll quick(ll a, ll b, ll c) {
    30     ll ret = 1;
    31     while (b > 0) {
    32         if (b & 1) ret = ret * a % c;
    33         b = b / 2;
    34         a = a * a % c;
    35     }
    36     return ret;
    37 }
    38 
    39 ll get_ans(int x, int n) {
    40     if (x == 1) return 0ll;
    41     ll ret = 0;
    42     ll inv = quick(x - 1, mod - 2, mod);
    43     for (int i = 1, j; i <= n; i = j + 1) {
    44         j = n / (n / i);
    45         ll sd = 2ll * s[n / i] - 1;
    46         ll a0 = quick(x, i, mod), qn = quick(x, j - i + 1, mod) + mod - 1;
    47         ll tmp = a0 * qn % mod;
    48         tmp = tmp * inv % mod;
    49         tmp = (tmp + mod - (j - i + 1)) % mod;
    50         tmp = sd * tmp % mod;
    51         ret += tmp;
    52         if (ret >= mod) ret -= mod;
    53     }
    54     return ret;
    55 }
    56 
    57 int main() {
    58 //    freopen("case.in", "r", stdin);
    59 
    60     phi_table();
    61     int T;
    62     cin >> T;
    63     while (T--) {
    64         int x, n;
    65         scanf("%d%d", &x, &n);
    66         cout << get_ans(x, n) << endl;
    67     }
    68 
    69     return 0;
    70 }
    代码君
  • 相关阅读:
    快速搭建http server
    cwmp part2 测试基础RPC
    Leetcode-5223 Queens That Can Attack the King(可以攻击国王的皇后)
    Leetcode-5222 Split a String in Balanced Strings(分割平衡字符串)
    Leetcode-5224 Dice Roll Simulation(掷骰子模拟)
    P2604-[ZJOI2010]网络扩容
    P2053-[SCOI2007]修车
    P2153-[SDOI2009]晨跑
    P2774 方格取数问题
    P2763-试题库问题
  • 原文地址:https://www.cnblogs.com/zhenhao1/p/5724177.html
Copyright © 2020-2023  润新知