[CCPC2017]湘潭邀请赛
题目链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/14/
D.模拟,按照原图每一个字符变成一个a*b的矩阵构造新矩阵。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 111; 5 int n, m, a, b; 6 char G[maxn][maxn]; 7 char GG[maxn][maxn]; 8 9 10 int main() { 11 // freopen("in", "r", stdin); 12 while(~scanf("%d%d%d%d",&n,&m,&a,&b)) { 13 memset(GG, 0, sizeof(GG)); 14 for(int i = 1; i <= n; i++) scanf("%s", G[i]+1); 15 for(int i = 1; i <= n; i++) { 16 for(int j = 1; j <= m; j++) { 17 for(int ii = 1; ii <= a; ii++) { 18 for(int jj = 1; jj <= b; jj++) { 19 GG[(i-1)*a+ii][(j-1)*b+jj] = G[i][j]; 20 } 21 } 22 } 23 } 24 for(int i = 1; i <= n*a; i++) printf("%s\n", GG[i]+1); 25 } 26 }
E.由于选取的区间点l,r都是不重复的,那么可以将整个问题描述为前缀和取2*m个点,每个点都不重复。
对整个数列排序,从两头取就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 100100; 6 LL a[maxn], s[maxn]; 7 int n, m, c; 8 9 int main() { 10 // freopen("in", "r", stdin); 11 while(~scanf("%d%d%d",&n,&m,&c)) { 12 memset(s, 0, sizeof(s)); 13 for(int i = 1; i <= n; i++) { 14 scanf("%I64d", &a[i]); 15 s[i] = s[i-1] + a[i]; 16 } 17 sort(s, s+n+1); 18 LL ret = 0; 19 LL tmp = 0; 20 int lo = 0, hi = n; 21 for(int i = 1; i <= m; i++) { 22 tmp += abs(s[hi]-s[lo]) - c; 23 hi--; lo++; 24 ret = max(ret, tmp); 25 } 26 printf("%I64d\n", ret); 27 } 28 return 0; 29 }
H.先用djikstra求出这棵树上的树直径,两个端点的再向其余边,最大的值加入到mst的权值中就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 typedef pair<LL, LL> pii; 6 typedef struct Edge { LL v, w, next; }Edge; 7 const LL maxn = 100100; 8 LL n, hcnt; 9 LL head[maxn]; 10 Edge edge[maxn<<1]; 11 LL d[2][maxn]; 12 13 void adde(LL u, LL v, LL w) { 14 edge[hcnt].v = v, edge[hcnt].w = w; 15 edge[hcnt].next = head[u]; head[u] = hcnt++; 16 } 17 18 LL dij(LL id, LL u) { 19 memset(d[id], -1, sizeof(d[id])); 20 priority_queue<pii> pq; 21 pq.push(pii(0, u)); d[id][u] = 0; 22 while(!pq.empty()) { 23 pii tmp = pq.top(); pq.pop(); 24 LL pw = tmp.first; 25 u = tmp.second; 26 for(LL i = head[u]; ~i; i=edge[i].next) { 27 LL v = edge[i].v, w = edge[i].w; 28 if(d[id][u] < pw) continue; 29 if(d[id][v] == -1 || d[id][v] > d[id][u] + w) { 30 d[id][v] = d[id][u] + w; 31 pq.push(pii(d[id][v], v)); 32 } 33 } 34 } 35 LL w = 0; 36 for(LL i = 1; i <= n; i++) { 37 if(w < d[id][i]) { 38 w = d[id][i]; u = i; 39 } 40 } 41 return u; 42 } 43 44 45 int main() { 46 // freopen("in", "r", stdin); 47 LL u, v, w; 48 while(~scanf("%I64d", &n)) { 49 hcnt = 0; 50 memset(head, -1, sizeof(head)); 51 for(LL i = 0; i < n - 1; i++) { 52 scanf("%I64d%I64d%I64d",&u,&v,&w); 53 adde(u, v, w); adde(v, u, w); 54 } 55 LL lo = dij(0, 1); 56 LL hi = dij(1, lo); 57 dij(0, hi); 58 LL ret = d[0][lo]; 59 for(LL i = 1; i <= n; i++) { 60 if(i == lo || i == hi) continue; 61 ret += max(d[0][i], d[1][i]); 62 } 63 printf("%I64d\n", ret); 64 } 65 }
I.简单推下会发现整个式子表示的是一个数列上选取两个点,求两个点的最小间隔。最小间隔是gcd(n,m),那么选中间的位置就会使式子最小。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 111; 6 LL n, m; 7 LL gcd(LL x, LL y) { 8 return y == 0 ? x : gcd(y, x % y); 9 } 10 11 int main() { 12 // freopen("in", "r", stdin); 13 while(cin >> n >> m) { 14 LL a = gcd(n, m); 15 LL b = 2 * n * m; 16 LL g = gcd(a, b); 17 a /= g, b /= g; 18 cout << a << "/" << b << endl; 19 } 20 }
A.相当于求伴随矩阵的第一列,用高斯消元求出矩阵的逆,输出第一行。
板子挂了啊。