《中国计量大学现代科技学院第四届“中竞杯”程序设计校赛部分题解》
A:签到
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 5e4+5; const int M = 1e2+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; string s[5]; bool vis[5][5]; int C(int n,int m) { if(n == m || m == 0) return 1; else return C(n - 1,m - 1) + C(n - 1,m); } int main() { for(int i = 0;i < 3;++i) cin >> s[i]; int num = 0; for(int i = 0;i < 3;++i) { for(int j = 0;j < 3;++j) if(s[i][j] == 'X') vis[i][j] = 1,num++; } int ma = 0; if(s[0][0] != 'X' && s[0][1] != 'X' && s[0][2] != 'X') ma++; if(s[1][0] != 'X' && s[1][1] != 'X' && s[1][2] != 'X') ma++; if(s[2][0] != 'X' && s[2][1] != 'X' && s[2][2] != 'X') ma++; if(s[0][0] != 'X' && s[1][0] != 'X' && s[2][0] != 'X') ma++; if(s[0][1] != 'X' && s[1][1] != 'X' && s[2][1] != 'X') ma++; if(s[0][2] != 'X' && s[1][2] != 'X' && s[2][2] != 'X') ma++; if(s[0][0] != 'X' && s[1][1] != 'X' && s[2][2] != 'X') ma++; if(s[0][2] != 'X' && s[1][1] != 'X' && s[2][0] != 'X') ma++; num = 9 - num; int tmp = C(num,3); if(ma == 0) printf("0\n"); else { int gcd = __gcd(tmp,ma); tmp /= gcd,ma /= gcd; printf("%d %d\n",ma,tmp); } // system("pause"); return 0; }
H:签到
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 5e4+5; const int M = 1e2+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int main() { int n; while(~scanf("%d",&n)) { int num = 0; while(n > 1) { if(n % 2 != 0) n--; else n /= 2; num++; } printf("%d\n",num); } // system("pause"); return 0; }
B:签到
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 2e5 + 5; const int M = 1e4+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int a[N],tot = 0,sz[N]; int main() { int n;n = read(); string s;cin >> s; for(int i = 0;i < s.size();++i) { if(i == 0) { a[++tot] = s[i] - 'A'; sz[tot] = 1; } else { if(s[i] == s[i - 1]) { sz[tot]++; } else { a[++tot] = s[i] - 'A'; sz[tot] = 1; } } } int ans = 0; for(int i = 1;i <= tot;++i) { if(i == tot) { ans = max(ans,sz[tot]); } else { if(a[i] == 0) { ans = max(ans,sz[i] + sz[i + 1]); } else { int ma = sz[i - 1] + sz[i] + sz[i + 1] + sz[i + 2]; ans = max(ma,ans); } } } printf("%d\n",ans); // system("pause"); return 0; }
D:签到
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 5e4+5; const int M = 1e2+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int main() { string s;cin >> s; string t;cin >> t; map<char,int> mp; for(auto v : s) mp[v]++; int f = 0; for(auto v : t) if(mp[v] != 0) f = 1; printf("%s\n",f ? "yes" : "no"); //system("pause"); return 0; }
C:我们贪心地考虑,如果以某个点为终点开始变形。
那么显然是要和最前面的一段满足的来变形,这样得到的代价一定是最优的。
枚举一下终点即可。这个起点可以用前缀和来找。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 2e5 + 5; const int M = 1e4+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int a[N],tot = 0,sz[N],sum[N],mi[N],nxt[N][2],pre[N][2];// 0 - A,1 - B int aa[N],bb[N],tot1 = 0,tot2 = 0; int main() { int n;n = read(); string s;cin >> s; for(int i = 0;i < s.size();++i) { if(s[i] == 'A') a[i + 1] = -1; else a[i + 1] = 1; } for(int i = 1;i <= n;++i) { sum[i] = sum[i - 1] + a[i]; if(mi[sum[i]] == 0) mi[sum[i]] = i; if(a[i] == -1) aa[++tot1] = i; else bb[++tot2] = i; } int nowa = 0,nowb = 0; for(int i = 1;i <= n;++i) { int pos1 = upper_bound(aa + 1,aa + tot1 + 1,i) - aa; if(pos1 > tot1) nxt[i][0] = 0; else nxt[i][0] = aa[pos1]; int pos2 = upper_bound(bb + 1,bb + tot2 + 1,i) - bb; if(pos2 > tot2) nxt[i][1] = 0; else nxt[i][1] = bb[pos2]; pre[i][0] = nowa,pre[i][1] = nowb; if(a[i] == -1) nowa = i; else nowb = i; // printf("nxt[%d][0] is %d nxt[%d][1] is %d\n",i,nxt[i][0],i,nxt[i][1]); // printf("pre[%d][0] is %d pre[%d][1] is %d\n",i,pre[i][0],i,pre[i][1]); } int ans = 0; for(int i = 1;i <= n;++i) { if(a[i] == -1) { int np = nxt[i][1]; if(np == 0) np = n + 1; else np = nxt[np][0]; if(np == 0) np = n + 1; ans = max(ans,np - i); } else { int np = nxt[i][0]; if(np == 0) np = n + 1; ans = max(ans,np - i); } if(mi[sum[i]] != 0 && mi[sum[i]] != i) { int len = i - mi[sum[i]]; // printf("part1 len is %d\n",len); int np = nxt[i][0]; if(np == 0) np = n + 1; len += np - i - 1; // printf("over1 len is %d\n",len); len += mi[sum[i]] - pre[mi[sum[i]] + 1][1]; // printf("over2 len is %d\n",len); ans = max(ans,len); } if(sum[i] == 0) { // printf("part2\n"); int len = i; int np = nxt[i][0]; if(np == 0) np = n + 1; len += np - i - 1; ans = max(ans,len); } // dbg(ans); } printf("%d\n",ans); //system("pause"); return 0; } //6 BBABAB
F:先对每一层背包。(三种情况)
然后就可以对全部层背包了,为了维护复杂度每层算到size个就够了。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 105; const int M = 1e4+5; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; int n,m,sz[N],w[N][M],dp[N][M],bs[N][N],pre[N][N]; int main() { n = read(),m = read(); for(int i = 1;i <= n;++i) { sz[i] = read(); for(int j = 1;j <= sz[i];++j) w[i][j] = read(); for(int j = 1;j <= sz[i];++j) pre[i][j] = pre[i][j - 1] + w[i][j]; } for(int i = 0;i <= n;++i) for(int j = 1;j <= m;++j) dp[i][j] = -1; for(int i = 1;i <= n;++i) { for(int j = 1;j <= sz[i];++j) { bs[i][j] = max(pre[i][j],pre[i][sz[i]] - pre[i][sz[i] - j]); for(int k = 1;k <= sz[i];++k) { if(k >= j) break; int ss = (j - k); bs[i][j] = max(bs[i][j],pre[i][k] + pre[i][sz[i]] - pre[i][sz[i] - ss]); } } } for(int i = 1;i <= n;++i) { for(int k = 1;k <= m;++k) { for(int j = 1;j <= sz[i];++j) { if(k >= j && dp[i - 1][k - j] != -1) { //printf("dp[%d][%d] is %d dp[%d][%d] is %d bs[%d][%d] is %d\n",i,k,dp[i][k],i - 1,k - j,dp[i - 1][k - j],i,j,bs[i][j]); dp[i][k] = max(dp[i][k],max(dp[i - 1][k],dp[i - 1][k - j] + bs[i][j])); } } } } printf("%d\n",dp[n][m]); // system("pause"); return 0; } /* 3 4 3 2 9 4 3 3 7 2 3 1 8 1 */
I:考虑四向bfs,dp松弛。
显然这样会TLE。可以发现这里是个我们要让长的路尽可能在满足的情况内。
所以我们直接bfs中动态维护答案,并且剪枝去过大的情况,这样的bfs复杂度应该是在总点数5000 * 5000左右。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 5e3+5; const int M = 1e3+5; const LL Mod = 1e9 + 7; #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read(){ int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();} return x * f; } } using namespace FASTIO; int n,m,sx,sy,ex,ey,dp[5005][5005][4],b[4][2] = {1,0,-1,0,0,1,0,-1},ans = INF; string a[5005]; struct Node{int x,y,step,fx;}; void bfs() { queue<Node> Q; for(int i = 0;i < 4;++i) { dp[sx][sy][i] = 0; Q.push(Node{sx,sy,0,i}); } while(!Q.empty()) { Node q = Q.front(); Q.pop(); if(q.step >= ans) continue; for(int i = 0;i < 4;++i) { int px = q.x + b[i][0]; int py = q.y + b[i][1]; int ma = q.step; if(i != q.fx) ma++; if(ma >= ans) continue; if(px >= 0 && px < n && py >= 0 && py < m && a[px][py] == '0' && ma < dp[px][py][i]) { dp[px][py][i] = ma; Q.push(Node{px,py,ma,i}); if(px == ex && py == ey) ans = min(ans,ma); } } } } int main() { n = read(),m = read(),sx = read(),sy = read(),ex = read(),ey = read(); for(int i = 0;i < n;++i) cin >> a[i]; for(int i = 0;i < n;++i) for(int j = 0;j < m;++j) for(int k = 0;k < 4;++k) dp[i][j][k] = INF; bfs(); printf("%d\n",ans == INF ? -1 : ans); //system("pause"); return 0; }
E:比赛的时候考虑了一下狄利克雷卷积,写了一会没卷出来就撤了。
看了下大佬们的代码,这里有个结论就是k >= 27这个值就是0。
至于怎么得出的我还没想出来。。
知道了这个结论之后就很简单了,递归求解。
对于里面的那层分块 + 记忆化一下然后就可以很快求出了。
代码咕