2019牛客暑期多校训练营 第五场
应该是最简单的一场了。
题目链接:https://ac.nowcoder.com/acm/contest/885#question
A:
显然输出n个n串在一起是答案。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 int t; 21 22 int main() { 23 scanf("%d", &t); 24 while (t--) { 25 int n; scanf("%d", &n); 26 for (int i = 1; i <= n; i++) printf("%d", n); 27 puts(""); 28 } 29 return 0; 30 }
B:
普通的快速幂绝对不行,要十分幂(log10)级别。完全就是十分幂模板题了。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 1e6 + 10; 21 int x0, x1, a, b, mod; 22 char s[maxn]; 23 24 struct Matrix { 25 ll mem[2][2]; 26 void init() { 27 memset(mem, 0, sizeof(mem)); 28 } 29 Matrix operator*(const Matrix &rhs)const { 30 Matrix ret; ret.init(); 31 for (int i = 0; i < 2; i++) { 32 for (int j = 0; j < 2; j++) { 33 for (int k = 0; k < 2; k++) 34 ret.mem[i][j] += mem[i][k] * rhs.mem[k][j]; 35 ret.mem[i][j] %= mod; 36 } 37 } 38 return ret; 39 } 40 } mAns, mBase; 41 42 ll solve(char *s) { 43 int len = strlen(s); 44 for (int i = len - 1; i >= 0; i--) { 45 int curr = s[i] - '0'; 46 while (curr--) mAns = mAns * mBase; 47 Matrix tmp = mBase * mBase; 48 mBase = tmp * tmp; 49 mBase = mBase * mBase * tmp; 50 } 51 return mAns.mem[0][1]; 52 } 53 54 int main() { 55 mAns.init(), mBase.init(); 56 scanf("%d%d%d%d", &x0, &x1, &a, &b); 57 scanf("%s %lld", s, &mod); 58 mAns.mem[0][0] = x1, mAns.mem[0][1] = x0; 59 mBase.mem[0][0] = a, mBase.mem[0][1] = 1, mBase.mem[1][0] = b; 60 ll ans = solve(s); 61 printf("%lld\n", ans); 62 return 0; 63 }
C:
给定一个递推序列xi=(a*xi-1+b)%mod,有q次查询,每次查询给定一个值p,找出最小的下标i,使得xi=p。
显然a≠0时xi与xi-1一一对应,可以直接套用大步小步算法(baby steps giant steps)。
D:
序列x和序列y从某个位置后开始会出现循环,但循环节不一样。
E:
状压dp。
F:
二分图最大独立集。
G:
考虑dp。对于所有长度大于m的合法的subsequence,用组合数计算;长度等于m的合法的subsequence,判断s最高位是否大于t最高位。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int mod = 998244353, maxn = 3e3 + 10; 21 int inv[maxn], fac[maxn], fiv[maxn], dp[2][maxn]; 22 23 int add(int a, int b) { 24 return a + b < mod ? a + b : a + b - mod; 25 } 26 27 int mul(int a, int b) { 28 return (ll)a * b % mod; 29 } 30 31 int C(int n, int m) { 32 return n < m ? 0 : mul(fac[n], mul(fiv[m], fiv[n - m])); 33 } 34 35 int main() { 36 inv[0] = inv[1] = fac[0] = fac[1] = fiv[0] = fiv[1] = 1; 37 for (int i = 2; i < maxn; i++) { 38 inv[i] = mul(inv[mod % i], mod - mod / i); 39 fac[i] = mul(fac[i - 1], i); 40 fiv[i] = mul(fiv[i - 1], inv[i]); 41 } 42 dp[0][0] = 1; 43 int t; scanf("%d", &t); 44 while (t--) { 45 int n, m; char s[maxn], t[maxn]; 46 scanf("%d%d", &n, &m); cin >> s >> t; 47 int ans = 0; 48 for (int i = 0; i < n; i++) 49 if (s[i] != '0') { 50 for (int j = m; i + j < n; j++) 51 ans = add(ans, C(n - i - 1, j)); 52 } 53 int *dp0 = dp[0], *dp1 = dp[1]; 54 size_t size = (m + 1) << 2; 55 memset(dp0, 0, size); 56 for (int i = 1; i <= n; i++) { 57 memcpy(dp1, dp0, size); 58 for (int j = 1; j <= m; j++) { 59 // 要拿当前位 60 if (s[n - i] > t[m - j]) dp1[j] = add(dp1[j], C(i - 1, j - 1)); 61 // 不拿当前位 62 if (s[n - i] == t[m - j]) dp1[j] = add(dp1[j], dp0[j - 1]); 63 } 64 swap(dp0, dp1); 65 } 66 printf("%d\n", add(ans, dp0[m])); 67 } 68 return 0; 69 }
H:
因为字母出现顺序满足偏序性质,所以可以考虑拓扑排序。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 1e5 + 10; 21 struct Edge { 22 int to, next; 23 Edge() {} 24 Edge(int to, int next): to(to), next(next) {} 25 } edge[maxn * 10]; 26 int head[maxn], inDeg[maxn], tot = 0, realMem[maxn * 10]; 27 char str[maxn], op[maxn]; 28 vector<int>vec, realPos[20]; 29 30 void addEdge(int u, int v) { 31 edge[tot].to = v; 32 edge[tot].next = head[u]; 33 inDeg[v]++; 34 head[u] = tot++; 35 } 36 37 int topologicalSort(int n) { 38 queue<int>q; 39 for (int i = 1; i <= n; i++) 40 if (!inDeg[i]) q.push(i); // 找最小的点 41 while (!q.empty()) { 42 int u = q.front(); 43 q.pop(); 44 vec.pb(u); 45 for (int i = head[u]; ~i; i = edge[i].next) { 46 int v = edge[i].to; 47 inDeg[v]--; 48 if (!inDeg[v]) q.push(v); 49 } 50 } 51 if (n == vec.size()) return 1; // 如果构建出来的图大小也为n,说明有解 52 else return 0; 53 } 54 55 int main() { 56 int n, m; scanf("%d%d", &n, &m); 57 m = m * (m - 1) >> 1; 58 for (int i = 0; i < maxn; i++) head[i] = -1; 59 int realLen = 0; 60 while (m--) { 61 int len; 62 scanf("%s %d", op, &len); 63 if (len != 0) scanf("%s", str); 64 int lastElement = -1; 65 int times[26]; 66 memset(times, 0, sizeof(times)); 67 for (int i = 0; i < len; i++) { 68 int currElement = str[i] - 'a'; 69 times[currElement]++; // 统计当前字符串中当前字母出现次数 70 if (realPos[currElement].size() < times[currElement]) { // 如果当前字符串中的某个字母出现次数超出了之前的统计,说明该字母有更多个 71 realPos[currElement].pb(++realLen); 72 realMem[realLen] = currElement; 73 } 74 if (lastElement != -1) addEdge(lastElement, realPos[currElement][times[currElement] - 1]); 75 lastElement = realPos[currElement][times[currElement] - 1]; 76 } 77 } 78 if (n != realLen) return puts("-1"), 0; 79 if (topologicalSort(n)) 80 for (int i = 0; i < vec.size(); i++) 81 printf("%c", 'a' + realMem[vec[i]]); 82 else puts("-1"); 83 return 0; 84 }
I:
不妨把三角形的一个定点固定在原点,并让一条边尽可能地贴近y轴,分为两种情况:完全贴合和不能贴合。
此时可以计算出在矩形边界的第二个点和第三个点,检验第三个点是否在矩形内部即可。
枚举所有情况,总共6种。注意答案输出顺序固定为XYZ三点。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-10 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 #define Point pair<double, double> 21 const double pi = acos(-1.0); 22 int w, h; 23 24 int solve(int a, int b, int c, Point &x, Point &y) { 25 double alpha = 0; 26 if (a <= h) x.first = 0, x.second = (double)a; 27 else { 28 x.first = sqrt((double)a * a - (double)h * h), x.second = (double)h; 29 alpha = acos((double)h / (double)a); 30 } 31 double beta = acos((double)(a * a + b * b - c * c ) / (2.0 * a * b)); 32 double gamma = pi / 2.0 - alpha - beta; 33 y.first = cos(gamma) * b, y.second = sin(gamma) * b; 34 if (y.first - w > eps || y.second - h > eps || y.first < -eps || y.second < -eps) return 0; 35 return 1; 36 } 37 38 int main() { 39 int t; scanf("%d", &t); 40 while (t--) { 41 Point x, y, z; 42 int a, b, c; 43 scanf("%d%d%d%d%d", &w, &h, &a, &b, &c); 44 if (solve(b, c, a, x, y) || solve(c, b, a, y, x)) { 45 z.first = z.second = 0; goto mark; 46 } 47 if (solve(a, c, b, x, z) || solve(c, a, b, z, x)) { 48 y.first = y.second = 0; goto mark; 49 } 50 if (solve(a, b, c, y, z) || solve(b, a, c, z, y)) { 51 x.first = x.second = 0; goto mark; 52 } 53 mark: 54 printf("%.10f %.10f %.10f %.10f %.10f %.10f\n", x.first, x.second, y.first, y.second, z.first, z.second); 55 } 56 return 0; 57 }
J:
先判断无解的情况,再利用dp+dfs求解。