标签:scanf time play can click 复杂度 names 定义 return
给出三种石头分别$a$,$b$,$c$个,每次拿石头的时候只能拿$1$个第一种石头和$2$个第二种石头,或者$1$个第二种石头和$2$个第三种石头,求最多能拿到多少?
先考虑后一种方案:这样子一共拿了$min(b, c/2)*3$个石头,然后剩下的石头再取$min((b-c/2)/2,a)*3$.
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n; 6 scanf("%d", &n); 7 while (n--) 8 { 9 int a, b, c; 10 scanf("%d%d%d", &a, &b, &c); 11 int ans = 0; 12 while (b > 0 && c > 1) 13 { 14 ans += 3; 15 b -= 1; 16 c -= 2; 17 } 18 while (b > 1 && a > 0) 19 { 20 ans += 3; 21 b -= 2; 22 a -= 1; 23 } 24 printf("%d\n", ans); 25 } 26 return 0; 27 }
给出无限个$n$种东西放进$m$个包且每个包中不出现重复元素的方案数,包里面可以不放东西。
考虑每个包里面都可以放或者不放某东西,一共$2^m-1$种,然后一共有$n$个物品,所以就是$(2^m-1)^n$种。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod = 1e9 + 7; 5 ll pow(ll a, ll b, ll p) 6 { 7 ll res = 1; 8 while (b) 9 { 10 if (b & 1) 11 res = res * a % p; 12 a = a * a % p; 13 b >>= 1; 14 } 15 return res; 16 } 17 int main() 18 { 19 ll n, m; 20 scanf("%lld%lld", &n, &m); 21 printf("%lld", pow((pow(2, m, mod) - 1ll + mod) % mod, n, mod)); 22 return 0; 23 }
定义$f(X,Y)$是$X$集合中$a$,和$Y$集合中的$b$满足$a>b$的数对的数量。给出一个$n\times n$的矩阵,元素是$1~n^2$,求出一种填数方式,使得对于所有的行,最大的$f(X_i,X_j)$最小。
考虑要最大的最小,首先发现因为所有的数都不一样,所以$f(X,Y)+f(Y,X)=n*n$,则我们需要找到一种分法,使得所有的行之间的$max(f(X,Y),f(Y,X))$等于$\frac {n*n}{2}$。所以,我们可以把这$n*n$个数按顺序分成$n$组,然后就第一组选$max$,第二组选$min$,第三组选$max$交替选够$n$个数,构成第一行,然后第二行从$min$选起,交替选够$n$个数,以此类推,观察矩阵的数可以发现规律,按规律写出代码即可。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 3e2 + 5; 4 int ans[N][N]; 5 int main() 6 { 7 int n; 8 scanf("%d", &n); 9 for (int i = 1; i <= n; ++i) 10 for (int j = 1; j <= n; ++j) 11 ans[i][j] = i + n * (j - 1); 12 for (int i = 2; i <= n; i += 2) 13 for (int j = 1; j <= n / 2; ++j) 14 swap(ans[j][i], ans[n - j + 1][i]); 15 for (int i = 1; i <= n; ++i) 16 for (int j = 1; j <= n; ++j) 17 printf("%d%c", ans[i][j], " \n"[j == n]); 18 return 0; 19 }
给出一个玩偶,它只能向前和向右,这个玩偶在$(1,1)$开始,走一个有障碍物的$n*m$的方格图,求能不能走完所有不是障碍物的格子。
理论上直接模拟就行,但是这样子时间复杂度是$O(n*m)$,所以我们预处理出每一行每一列所有障碍物,排好序,这样子就可以用二分查找找出前面的第一个障碍物。这样子时间就降到$O(nlogn)$了。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5 + 5; 4 typedef long long ll; 5 vector<int> G1[N]; 6 vector<int> G2[N]; 7 int main() 8 { 9 int n, m, k; 10 scanf("%d%d%d", &n, &m, &k); 11 for (int i = 1; i <= k; ++i) 12 { 13 int a, b; 14 scanf("%d%d", &a, &b); 15 G1[a].push_back(b); 16 G2[b].push_back(a); 17 } 18 for (int i = 1; i <= n; ++i) 19 sort(G1[i].begin(), G1[i].end()); 20 for (int i = 1; i <= m; ++i) 21 sort(G2[i].begin(), G2[i].end()); 22 bool f = 0; 23 ll ans = 1; 24 int x = 1, y = 1; 25 int up = 1, down = n, left = 1, right = m; 26 int dir = 0; 27 while (1) 28 { 29 int ny, nx; 30 if (dir == 0) //右方向 31 { 32 int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin(); 33 nx = x; 34 if (pos == G1[x].size()) 35 ny = right; 36 else 37 ny = min(right, G1[x][pos] - 1); 38 up = x + 1; 39 } 40 else if (dir == 1) //下方向 41 { 42 int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin(); 43 ny = y; 44 if (pos == G2[y].size()) 45 nx = down; 46 else 47 nx = min(down, G2[y][pos] - 1); 48 right = y - 1; 49 } 50 else if (dir == 2) 51 { 52 int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin() - 1; 53 nx = x; 54 if (pos < 0) 55 ny = left; 56 else 57 ny = max(left, G1[x][pos] + 1); 58 down = x - 1; 59 } 60 else if (dir == 3) 61 { 62 int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin() - 1; 63 ny = y; 64 if (pos < 0) 65 nx = up; 66 else 67 nx = max(up, G2[y][pos] + 1); 68 left = y + 1; 69 } 70 if (nx == x && ny == y && f) 71 break; 72 dir = (dir + 1) % 4; 73 ans += abs(nx - x) + abs(ny - y); 74 x = nx; 75 y = ny; 76 f = 1; 77 } 78 if (ans == (ll)n * m - k) 79 printf("Yes\n"); 80 else 81 printf("No\n"); 82 return 0; 83 }
AC代码:
标签:scanf time play can click 复杂度 names 定义 return
原文地址:https://www.cnblogs.com/Aya-Uchida/p/13266242.html