BestCoder Round #41

3/4

闲来无事打打BC,想必也是极好的,先来个flag:我要刷完所有的BC!!

 

题A hdu 5228

题意:给你五张牌,问你能够换最少的牌数实现同花顺。

题解:暴力乱搞,才五张牌,枚举所有组成同花顺的可能,然后匹配看还要补多少张即可。

 

 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 bool vis[10];
15 
16 struct Node {
17   char c;
18   int v;
19 } nodes[10];
20 
21 int slove(Node tmp) {
22   int s = tmp.v - 5 + 1, e = tmp.v, ret = 5;
23   s = max(1, s); e = min(e, 10);
24   for (int i = s; i <= e; i++) {
25     memset(vis, 0, sizeof vis);
26     int cnt = 0;
27     for (int j = 0; j < 5; j++) {
28       char c = tmp.c; int v = i + j;
29       if (v > 13) v -= 13;
30 //      cout << c << v << ' ';
31       for (int k = 0; k < 5; k++) if (c == nodes[k].c && v == nodes[k].v) vis[k] = 1;
32     }
33     for (int j = 0; j < 5; j++) if (!vis[j]) cnt++;
34     ret = min(ret, cnt);
35     if (ret == 0) return ret;
36   }
37   return ret;
38 }
39 
40 int main() {
41 //  freopen("case.in", "r", stdin);
42   int T;
43   cin >> T;
44   while (T--) {
45     for (int i = 0; i < 5; i++) {
46       scanf(" %c%d", &nodes[i].c, &nodes[i].v);
47 //      cout << nodes[i].c << ' ' << nodes[i].v << endl;
48     }
49     int ans = 5;
50     for (int i = 0; i < 5; i++) {
51       ans = min(ans, slove(nodes[i]));
52     }
53     printf("%d
", ans);
54   }
55   return 0;
56 }
代码君

题B hdu 5229

题意:给你n个字符串,然后玩一个游戏:任意选两个串,然后有两种玩法:

1、删掉最后一个字符;

2、如果两个串一样,那么就可以删除这两个串;

谁不能操作谁输。显然不可能制造相同的让别人赢,所以只可能是一开始用到第二个操作,也就是如果两个串一样,那么必胜,否则就看两个串的长度,长度为偶数就输,否则就赢。写个hash判一下多少个一样的即可。

 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 #define base 131
15 
16 const int maxn = 2e5 + 10;
17 map<ull,int> mp;
18 char s[maxn];
19 
20 ll gcd(ll a, ll b) {
21   if (!b) return a;
22   return gcd(b, a % b);
23 }
24 
25 int main() {
26 //  freopen("case.in", "r", stdin);
27   int T;
28   cin >> T;
29   while (T--) {
30     int n;
31     scanf("%d", &n);
32     mp.clear();
33     ll res = 0, odd = 0, even = 0;
34     for (int i = 0; i < n; i++) {
35       scanf("%s", s);
36       int l = strlen(s);
37       if (l & 1) { res += even; odd++; }
38       else { res += odd; even++; }
39       ull x = 0;
40       for (int j = 0; j < l; j++) x = x * base + s[j];
41       if (mp.find(x) == mp.end()) mp[x] = 1;
42       else {
43         res += mp[x];
44         mp[x]++;
45       }
46     }
47 //    cout << res << endl;
48     if (!res) printf("0/1
");
49     else {
50       ll tmp = 1ll * n * (n - 1) / 2;
51       ll d = gcd(res, tmp);
52       printf("%I64d/%I64d
", res / d, tmp / d);
53     }
54   }
55   return 0;
56 }
代码君

题C hdu 5330

题意:给你1~n-1的数,问你能组成l~r有多少种方案(r < n);

题解:整数拆分问题,如果用普通的dp肯定超时,这个问题还比较经典(虽然我不会)。dp[i][j]表示用了i个不同的数,组成j的方案数。显然这个i最大就是i * (i + 1) / 2 <= r;所以整个复杂度是O(n * ),怎么转移呢?这是比较关键的问题:

dp[i][j] = dp[i][j - i] + dp[i - 1][j - i];

dp[i][j - i]表示组成j - i,用了i个数的所有方案中的数都加上1,那么不就组成j了吗;

dp[i - 1]j - i]表示上述方案少了有1这种情况,那么我们就把1补上,当然所有的方案不能有1,所以就是dp[i - 1][j - i],还可以放一个数,那就是1了。最后注意0也算一种方案,所以l == 0的时候要加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 maxn = 1e5 + 100, mod = 998244353;
15 int dp[2][maxn];
16 
17 void add(int& a, int b) {
18   a += b;
19   if (a >= mod) a -= mod;
20 }
21 
22 int main() {
23 //  freopen("case.in", "r", stdin);
24   int T;
25   cin >> T;
26   while (T--) {
27     int n, c, l, r;
28     scanf("%d%d%d%d", &n, &c, &l, &r);
29     l -= c; r = min(r - c, n - 1);
30     int cur = 0, ans = 0;
31     memset(dp[0], 0, sizeof dp[0]);
32     dp[0][0] = 1;
33     for (int i = 1; i * (i + 1) / 2 <= r; i++) {
34       cur ^= 1;
35       memset(dp[cur], 0, sizeof dp[cur]);
36       for (int j = i * (i + 1) / 2; j <= r; j++) {
37         add(dp[cur][j], dp[cur][j - i]);
38         add(dp[cur][j], dp[cur ^ 1][j - i]);
39         if (l <= j && j <= r) add(ans, dp[cur][j]);
40       }
41     }
42     if (l <= 0) add(ans, 1);
43     printf("%d
", ans);
44   }
45   return 0;
46 }
代码君

 

题D hdu 5331

题意:不会

题解:不会(ps:我只做人做的题!!

 

原文地址:https://www.cnblogs.com/zhenhao1/p/5518272.html