赞
踩
目录
2 + 2 * 9 + 2 * = 1478
1478
该题有异议如果012算顺子,答案为 140120
0121
0122
0123
0124
0125
0126
0127
0128
0129
1012
1123
1230
1231
如果012不算顺子,答案为 40123
1123
1230
1231
10 20 99
8
算法标签:模拟
看n的取值范围,不能暴力枚举,会TLE。利用每七天一循环。
代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- typedef long long LL;
-
- int main()
- {
- LL a, b, n;
- cin >> a >> b >> n;
- LL s = 5 * a + 2 * b;
- LL res = n / s * 7;
- n %= s;
- LL d[] = {a, a, a, a, a, b, b};
- for(int i = 0; n > 0; i++)
- {
- n -= d[i];
- res++;
- }
- cout << res << endl;
-
- return 0;
- }
3
- 4
- 2
- 4
算法标签:模拟
从第i棵树开始:
向右走:第i棵树的最大高度为:2(n - i);
向左走:第i棵树的最大高度为:2(i - 1).
两值取max即为最大高度
代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- int main()
- {
- int n;
- cin >> n;
- for(int i = 1; i <= n; i++)
- {
- cout << max(2 * (i - 1), 2 * (n - i)) << endl;
- }
-
- return 0;
- }
- 11
- 3
- 10 4 0
- 3
- 1 2 0
94
算法标签:贪心
将321转换为65过程:
3 * 10 * 2 + 2 * 2 + 1 = 65。
差值最小,是 a,b的每位数的进制最低。
欲使a-b最小,只需使得各位数字取得合法范围内的最小进制即可,具体做法就是对a和b中相同数位的数字取max(a[i] + 1, b[i] + 1,2).
+1是因为:比如八进制, 最大数字为7, 求的是进制所以要+1.
因为a >= b, b的位数如果比a少,要在高位上补0,从低位向高位存取
代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 100010, mod = 1000000007;
-
- int n, ma, mb, m;
- int a[N], b[N];
- int g[N]; // 各位进制
- LL w[N];
- LL A, B;
-
- int main()
- {
- cin >> n;
- cin >> ma;
- for(int i = ma - 1; i >= 0; i--) cin >> a[i];
- cin >> mb;
- for(int i = mb - 1; i >= 0; i--) cin >> b[i];
-
- int m = max(ma, mb);
-
- // 确定各位进制
- for(int i = m - 1; i >= 0; i--)
- g[i] = max({a[i] + 1, b[i] + 1, 2});
-
- // 计算各位权重
- w[0] = 1;
- for(int i = 1; i <= m - 1; i++)
- w[i] = w[i - 1] * g[i - 1] % mod;
-
- // 计算A
- for(int i = m - 1; i >= 0; i--)
- A = (A + a[i] * w[i]) % mod;
-
- // 计算B
- for(int i = m - 1; i >= 0; i--)
- B = (B + b[i] * w[i]) % mod;
-
- LL res = (A - B + mod) % mod;
-
- cout << res << endl;
-
- return 0;
- }
优化后代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 100010, mod = 1000000007;
-
- int n, ma, mb, m;
- int a[N], b[N];
-
- int main()
- {
- cin >> n;
- cin >> ma;
- for(int i = ma - 1; i >= 0; i--) cin >> a[i];
- cin >> mb;
- for(int i = mb - 1; i >= 0; i--) cin >> b[i];
-
- int m = max(ma, mb);
- int res = 0;
- for(int i = m - 1; i >= 0; i--) // A - B
- res = (res * (LL)max({a[i] + 1, b[i] + 1, 2}) + a[i] - b[i]) % mod;
-
- cout << res << endl;
-
- return 0;
- }
- 3 4 10
- 1 2 3 4
- 5 6 7 8
- 9 10 11 12
19
算法标签:前缀和,双指针
直接用二维前缀和枚举,O()会超时,所以用双指针优化。
把每一列看成一个元素, 把二维问题变成一维问题,
代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 505;
- int n, m, k;
- int s[N][N]; // 每一列上的前缀和
-
- int main()
- {
- cin >> n >> m >> k;
- for(int i = 1; i <= n; i++)
- for(int j = 1; j <= m; j++)
- {
- cin >> s[i][j];
- s[i][j] += s[i - 1][j];
- }
- LL res = 0;
- for(int i = 1; i <= n; i++) // i, j表示上下边界, l,r表示左右边界
- for(int j = i; j <= n; j++)
- for(int l = 1, r = 1, sum = 0; r <= m; r++)
- {
- sum += s[j][r] - s[i - 1][r];
- while(sum > k)
- {
- sum -= s[j][l] - s[i - 1][l];
- l++;
- }
- res += r - l + 1;
- }
- cout << res << endl;
-
- return 0;
- }
3
5
算法标签:状态压缩DP
f(i, j)表示已经操作完前i - 1列,且第i列的状态为j的所有方案的集合
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- const int N = 1e7 + 10, mod = 1e9 + 7;
-
- int n;
- int g[4][4] = {
- {1, 1, 1, 1},
- {0, 0, 1, 1},
- {0, 1, 0, 1},
- {1, 0, 0, 0},
- };
- int f[N][4];
-
- int main()
- {
- cin >> n;
- f[1][0] = 1;
-
- for(int i = 1; i <= n; i++)
- for(int j = 0; j < 4; j++)
- for(int k = 0; k < 4; k++)
- f[i + 1][k] = (f[i + 1][k] + f[i][j] * g[j][k]) % mod;
-
- cout << f[n + 1][0] << endl;
-
- return 0;
- }
- 2 1
- 2 2 4
- 4 4 2
- 0 0 5
2
算法标签:图的遍历,DFS, BFS, 哈希
需要构建有向图,对于每个地雷,只需遍历周围一圈r内坐标即可,由坐标点知道是否有地雷,需要用到哈希表, 该题需要手写哈希表。
代码:
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <algorithm>
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 50010, M = 999997;
-
- int n, m;
- struct circle
- {
- int x, y, r;
- }cir[N];
- LL h[M];
- int id[M];
- bool st[M];
-
- LL get_key(int x, int y) // 得到每个坐标的哈希值
- {
- return x * 1000000001ll + y;
- }
-
- int find(int x, int y) // 找到该坐标在哈希数组中存储下标t
- {
- LL key = get_key(x, y);
- int t = (key % M + M) % M;
- while(h[t] != -1 && h[t] != key) //如果该位置已被占用并且不等于要求的哈希值
- if(++t == M)
- t = 0;
-
- return t;
- }
-
- int sqr(int x)
- {
- return x * x;
- }
-
- void dfs(int x, int y, int r)
- {
- st[find(x, y)] = true;
- for(int i = x - r; i <= x + r; i++)
- for(int j = y - r; j <= y + r; j++)
- if(sqr(i - x) + sqr(j - y) <= sqr(r))
- {
- int t = find(i, j);
- if(id[t] && !st[t])
- dfs(i, j, cir[id[t]].r);
- }
- }
-
- int main()
- {
- scanf("%d%d", &n, &m);
- memset(h, -1, sizeof h);
- for(int i = 1; i <= n; i++)
- {
- int x, y, r;
- scanf("%d%d%d", &x, &y, &r);
- cir[i] = {x, y, r};
-
- int t = find(x, y);
- if(h[t] == -1) h[t] = get_key(x, y);
-
- // 如果该id没有没占用,或者找到了同一坐标点更大半径的地雷
- if(!id[t] || cir[id[t]].r < r)
- id[t] = i;
- }
- while(m--)
- {
- int x, y, r;
- scanf("%d%d%d", &x, &y, &r);
-
- // 枚举周围的正方形区域,然后判断是否在圆内
- for(int i = x - r; i <= x + r; i++)
- for(int j = y - r; j <= y + r; j++)
- if(sqr(i - x) + sqr(j - y) <= sqr(r))
- {
- int t = find(i, j);
- if(id[t] && !st[t])
- dfs(i, j, cir[id[t]].r);
- }
- }
-
- int res = 0;
- for(int i = 1; i <= n; i++)
- if(st[find(cir[i].x, cir[i].y)])
- res++;
-
- cout << res << endl;
-
- return 0;
- }
5 10
14
算法标签:DP
f(i, j, k)表示一共遇到i个店, j朵花, 且有k个单位酒的方案的集合
集合按最后一步遇到的是花还是店来划分
所有酒的数量必须小于等于m
最后为店:f(i - 1, j, k / 2) , i >= 1 且 k / 2为整数
最后为花:f(i, j - 1, k + 1), j >= 1
倒数第二步为:f(n, m - 1, 1)
代码:
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- const int N = 105, mod = 1e9 + 7;
- int f[N][N][N];
-
- int main()
- {
- int n, m;
- cin >> n >> m;
- f[0][0][2] = 1;
- for(int i = 0; i <= n; i++)
- for(int j = 0; j <= m; j++)
- for(int k = 0; k <= m; k++)
- {
- if(i >= 1 && k % 2 == 0)
- f[i][j][k] = (f[i][j][k] + f[i - 1][j][k / 2]) % mod;
- if(j >= 1)
- f[i][j][k] = (f[i][j][k] + f[i][j - 1][k + 1]) % mod;
- }
- cout << f[n][m - 1][1] << endl;
-
- return 0;
- }
- 6
- 2 1 4 2 6 7
5
算法标签:贪心
- #include <iostream>
- #include <algorithm>
- #include <cstdio>
- #include <cmath>
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 200010, M = 10;
-
- int n, m;
- LL f[N][M];
-
- int main()
- {
- scanf("%d", &n);
- LL stk[M];
-
- int res = 0;
- for(int i = 0; i < n; i++)
- {
- LL x;
- int top = 0;
- scanf("%lld", &x);
- while(x > 1) stk[++top] = x, x = sqrt(x / 2 + 1);
- res += top; //top为操作次数
- m = max(m, top); //m表示所有数中的最大的操作次数
- for(int j = 0, k = top; k; j++, k--)
- f[i][j] = stk[k];
- }
- for(int i = 0; i < m; i++)
- for(int j = 1; j < n; j++)
- if(f[j][i] && f[j][i] == f[j - 1][i]) //当该数与前一个数相等时
- res--;
-
- cout << res << endl;
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。