2017 JUST Programming Contest 2.0 题解
【题目链接】
首先,n>m或k>m或k>n就无解。
设p=AB,ans=Ck−1n−1(AB)k(B−AB)n−k=(n−1)!×Ak×(B−A)n−k(k−1)!×(n−k)!×Bn。令分子为p,分母为q,最终的答案为p*(q的逆元)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <bits/stdc++.h> using namespace std; const long long mod = 1e9 + 7; const int maxn = 2e5 + 10; long long f[maxn]; long long m, n, k; char s[maxn]; long long qpow( long long a, long long b) { long long res = 1LL; a = a % mod; while (b) { if (b & 1) res = (res * a) % mod; b = b / 2; a = (a * a) % mod; } return res; } long long extend_gcd( long long a, long long b, long long &x, long long &y) { if (a==0&&b==0) return -1; //无最大公约数 if (b==0){x=1;y=0; return a;} long long d=extend_gcd(b,a%b,y,x); y-=a/b*x; return d; } //*********求逆元素******************* //ax = 1(mod n) long long mod_reverse( long long a, long long n) { long long x,y; long long d=extend_gcd(a,n,x,y); if (d==1) return (x%n+n)%n; else return -1; } void init() { f[0] = 1LL; for ( long long i = 1; i <= 100000; i ++) { f[i] = (f[i - 1] * i) % mod; } } int main() { init(); cin >> m >> n >> k >> s; if (n > m || k > m || k > n) { printf ( "0\n" ); return 0; } if (s[0] == '1' && n == k) { printf ( "1\n" ); return 0; } if (s[0] == '1' ) { printf ( "0\n" ); return 0; } if (s[0] == '0' && s[2] == '0' && s[3] == '0' && s[4] == '0' ) { printf ( "0\n" ); return 0; } long long A = 0; long long B = 1000LL; for ( int i = 2; i <= 4; i ++) { A = A * 10LL + s[i] - '0' ; } long long p, q; p = f[n - 1] * qpow(A, k) % mod; p = p * qpow(B - A, n - k) % mod; q = f[k - 1] * f[n - k] % mod; q = q * qpow(B, n) % mod; long long x = p * mod_reverse(q, mod) % mod; printf ( "%lld\n" , x); return 0; } |
B - So You Think You Can Count?
设dp[i]表示以i为结尾的方案数,每个位置最多往前扫10位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <bits/stdc++.h> using namespace std; const long long mod = 1e9 + 7; const int maxn = 1e5 + 10; char s[maxn]; int n; long long dp[maxn]; long long DP( int x) { if (x < 0) return 1LL; return dp[x]; } int main() { scanf ( "%d" , &n); scanf ( "%s" , s); int len = strlen (s); dp[0] = 1LL; for ( int i = 1; i < len; i ++) { int tmp[20]; for ( int j = 0; j <= 9; j ++) { tmp[j] = 0; } for ( int pre = i; pre >= 0; pre --) { if (tmp[s[pre] - '0' ]) break ; tmp[s[pre] - '0' ] = 1; dp[i] = (dp[i] + DP(pre - 1)) % mod; } } printf ( "%lld\n" , dp[len - 1]); return 0; } |
最短路,数据有点水,没把spfa卡住。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; int S, T, n, m; char name[maxn][25]; int h[maxn], nx[maxn], to[maxn], c[maxn], sz; int t1[30], t2[30]; int cost( int x, int y) { memset (t1, 0, sizeof t1); memset (t2, 0, sizeof t2); for ( int i = 0; name[x][i]; i ++){ if (name[x][i] >= 'a' && name[x][i] <= 'z' ) { t1[name[x][i] - 'a' ] ++; } if (name[x][i] >= 'A' && name[x][i] <= 'Z' ) { t1[name[x][i] - 'A' ] ++; } } for ( int i = 0; name[y][i]; i ++){ if (name[y][i] >= 'a' && name[y][i] <= 'z' ) { t2[name[y][i] - 'a' ] ++; } if (name[y][i] >= 'A' && name[y][i] <= 'Z' ) { t2[name[y][i] - 'A' ] ++; } } int num = 0; for ( int i = 0; i < 26; i ++) { if (t1[i] && t2[i]) num ++; } return num; } void add( int x, int y, int z) { to[sz] = y; c[sz] = z; nx[sz] = h[x]; h[x] = sz++; } int dis[maxn], f[maxn]; void spfa() { for ( int i = 1 ;i <= n; i ++) { f[i] = 0; dis[i] = 0x7FFFFFFF; } queue< int > Q; Q.push(S); f[S] = 1; dis[S] = 0; while (!Q.empty()) { int top = Q.front(); Q.pop(); f[top] = 0; for ( int i = h[top]; i != -1; i = nx[i]) { if (dis[top] + c[i] < dis[to[i]]) { dis[to[i]] = dis[top] + c[i]; if (f[to[i]] == 0) { f[to[i]] = 1; Q.push(to[i]); } } } } } int main() { scanf ( "%d%d" , &n, &m); for ( int i = 1; i <= n; i ++) { scanf ( "%s" , name[i]); h[i] = -1; } for ( int i = 1; i <= m; i ++) { int u, v; scanf ( "%d%d" , &u, &v); add(u, v, cost(u, v)); add(v, u, cost(u, v)); } scanf ( "%d%d" , &S, &T); spfa(); printf ( "%d\n" , dis[T]); return 0; } |
模拟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 10; char s[maxn]; int main() { int T; scanf ( "%d" , &T); while (T --) { scanf ( "%s" , s); int num1=0, num2=0, num3=0; for ( int i = 0; s[i];i ++) { if (s[i]>= 'a' &&s[i]<= 'z' ) num1++; else if (s[i]>= 'A' &&s[i]<= 'Z' ) num1++; else if (s[i]>= '0' &&s[i]<= '9' ) num2++; else if (s[i] == '!' || s[i] == '?' ||s[i] == '@' ) { num3++; } } if (num1 < 4) { printf ( "The last character must be a letter.\n" ); continue ; } if (num2 < 4) { printf ( "The last character must be a digit.\n" ); continue ; } if (num3 < 2) { printf ( "The last character must be a symbol.\n" ); continue ; } printf ( "The last character can be any type.\n" ); } return 0; } |
由于验证的复杂度只有O(26),因此可以枚举答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int n, m; char s[maxn]; long long f[maxn]; int main() { scanf ( "%s" , s); for ( int i = 0; s[i]; i ++) { f[s[i] - 'a' ] ++; } long long ans = -1; long long mn = -1; for ( long long i = 2; i <= 300000; i ++) { long long tmp = 0; for ( int j = 0; j < 26; j ++) { tmp = tmp + (f[j] % i) * f[j]; } if (mn == -1 || tmp < mn) { mn = tmp; ans = i; } } printf ( "%lld\n" , ans); return 0; } |
二分查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int n, m; int a[maxn]; int main() { scanf ( "%d" , &n); for ( int i = 1; i <= n; i ++) scanf ( "%d" , &a[i]); sort(a + 1, a + 1 + n); scanf ( "%d" , &m); while (m --) { int x; scanf ( "%d" , &x); int L = 1, R = n, pos = -1; while (L <= R) { int mid = (L + R) / 2; if (a[mid] >= x) pos = mid, R = mid - 1; else L = mid + 1; } if (pos == -1) printf ( "Dr. Samer cannot take any offer :(.\n" ); else printf ( "%d\n" , a[pos]); } return 0; } |
模拟。
1 2 3 4 5 6 7 8 9 10 | #include <bits/stdc++.h> using namespace std; int main() { int n, m; cin>> n>>m; if (m % n == 0) printf ( "YES\n" ); else printf ( "NO\n" ); return 0; } |
这题为单调栈经典问题,但是由于数值范围只有50,因此可以枚举数值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; int n, m; int a[maxn]; int b[maxn]; int num[maxn]; int main() { scanf ( "%d" , &n); for ( int i = 1; i <= n; i ++) { scanf ( "%d" , &a[i]); } for ( int i = 0; i<= 100; i ++) num[i] = 200000; for ( int j = n; j>=1; j--) { b[j] = 200000; for ( int k = 50; k >= a[j] + 1; k--){ if (num[k] < b[j]) b[j] = num[k]; } num[a[j]] = j; if (b[j] != 200000) b[j] = a[b[j]]; else b[j] = -1; } for ( int i =1 ;i <= n; i ++) { printf ( "%d " , b[i]); } return 0; } |
I - Husam and the Broken Present 1
对主对角线开根号来求解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <bits/stdc++.h> using namespace std; int main() { int n; cin>> n; int x; for ( int i = 1; i <= n; i ++) { for ( int j = 1; j <= n; j++){ cin>>x; if (i == j){ int num = sqrt (1.0 * x); while (num * num > x) num--; while (num*num<x)num++; printf ( "%d " , num); } } } return 0; } |
J - Husam and the Broken Present 2
先删除被包含的那些数组,剩下的可以进行状压dp来决策放置顺序。dp[st][v]表示有st状态里面的子数组已经放置好了,最后放的是v的最小花费,和TSP是一样的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #include <bits/stdc++.h> using namespace std; const int maxn = 1000; vector< int > vec[maxn], t[maxn]; int cost[20][20]; int n; int dp[70000][17]; int han(vector< int >& a, vector< int >& b) { // a 是否在 b 中 if (b.size() < a.size()) return 0; for ( int i = 0; i < b.size(); i ++) { int L = i, R = i + a.size() - 1; if (R >= b.size()) break ; int fail = 0; for ( int j = 0; j < a.size(); j ++) { if (a[j] != b[L + j]) fail = 1; } if (fail == 0) return 1; } return 0; } int cal( int x, int y) { // x 后面 接 y int res = 0; for ( int i = 0; i < t[x].size(); i ++) { if (t[x].size() - i > t[y].size()) continue ; int fail = 0; for ( int j = i; j < t[x].size(); j ++) { if (t[x][j] != t[y][j - i]) fail = 1; } //printf("!!! %d, %d\n", i, fail); if (fail == 0) { res = t[x].size() - i; break ; } } return t[y].size() - res; } bool cmp( const vector< int > &a, const vector< int > &b) { return a.size() > b.size(); } int main() { scanf ( "%d" , &n); for ( int i = 0; i < n; i ++) { int x; scanf ( "%d" , &x); while (x--){ int p; scanf ( "%d" , &p); vec[i].push_back(p); } } sort(vec, vec + n, cmp); int sz = 0; t[sz++] = vec[0]; for ( int i = 1; i < n; i ++) { int fail = 0; for ( int j = 0; j < sz; j ++) { if (han(vec[i], t[j])) { fail = 1; break ; } } if (fail) continue ; t[sz ++] = vec[i]; } n = sz; /* for(int i = 0; i < n; i ++) { for(int j = 0; j < t[i].size(); j ++) { cout << t[i][j] << " "; } cout << endl; } */ for ( int i = 0; i < n; i ++) { for ( int j = 0; j < n; j ++) { if (i == j) continue ; cost[i][j] = cal(i, j); } } for ( int st = 0; st < (1 << n); st ++) { for ( int i = 0; i < n; i ++) { dp[st][i] = 200000; } } for ( int i = 0; i < n; i ++) { dp[1 << i][i] = t[i].size(); } for ( int st = 1; st < (1 << n); st ++) { for ( int pre = 0; pre < n; pre ++) { if (((1 << pre) & st) == 0) continue ; for ( int now = 0; now < n; now ++) { if ((1 << now) & st) continue ; dp[st | (1 << now)][now] = min(dp[st | (1 << now)][now], dp[st][pre] + cost[pre][now]); } } } int ans = dp[(1 << n) - 1][0]; for ( int i = 0; i < n; i ++) { ans = min(ans, dp[(1 << n) - 1][i]); } printf ( "%d\n" , ans); return 0; } /* 3 2 1 2 4 3 4 5 6 3 2 3 4 */ |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
· 如何做好软件架构师
· 记录一次线上服务OOM排查
· Linux实时系统Xenomai宕机问题的深度定位过程
· 2025年广告第一单,试试这款永久免费的开源BI工具
· o3 发布了,摔碎了码农的饭碗
· [.NET] API网关选择:YARP还是Ocelot?
· 用 2025 年的工具,秒杀了 2022 年的题目。
· C#+ WPF 实现蓝牙转WIFI计步上位机
2017-02-19 CodeForces 767D Cartons of milk
2017-02-19 CodeForces 767C Garland
2017-02-19 CodeForces 767B The Queue
2016-02-19 ZOJ 3780 Paint the Grid Again
2016-02-19 [期待神犇降临] 前几天想到的一个问题。
2016-02-19 HDU 2809 God of War