大学生程序设计邀请赛(华东师范大学)
比赛链接:http://acm.ecnu.edu.cn/contest/11/
E.水题,手工模拟下就会发现这就是在做求gcd的步骤,所以用lcm除以x就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 LL x, n; 6 7 int main() { 8 // freopen("in", "r", stdin); 9 while(~scanf("%lld%lld",&x,&n)) { 10 for(LL i = 2; i <= n; i++) { 11 cout << x / __gcd(x, i) * i / x << endl; 12 } 13 } 14 return 0; 15 }
A.很烦人,因为unicode的问题,python写起来很轻松。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1010010; 5 char a[maxn]; 6 7 int main() { 8 // freopen("in", "r", stdin); 9 int T, _ = 1; 10 scanf("%d",&T); 11 while(T--) { 12 memset(a, 0, sizeof(a)); 13 scanf("%s",a); 14 int len=strlen(a); 15 if(a[len-1]>='1'&&a[len-1]<='4') { 16 int aa=0,ee=0,ii=0,oo=0,uu=0,vv=0; 17 printf("Case %d: ", _++); 18 for(int i=0;i<len-1;i++) { 19 if(a[i]=='a')aa++; 20 if(a[i]=='e')ee++; 21 if(a[i]=='i')ii++; 22 if(a[i]=='o')oo++; 23 if(a[i]=='u')uu++; 24 if(a[i]=='v')vv++; 25 } 26 if(aa) { 27 for(int i=0;i<len-1;i++) { 28 if(a[i]=='a') { 29 if(a[len-1]=='1')printf("ā"); 30 if(a[len-1]=='2')printf("á"); 31 if(a[len-1]=='3')printf("ǎ"); 32 if(a[len-1]=='4')printf("à"); 33 } 34 else printf("%c",a[i]); 35 } 36 printf("\n"); 37 } 38 else { 39 if(oo) { 40 for(int i=0;i<len-1;i++) { 41 if(a[i]=='o') { 42 if(a[len-1]=='1')printf("ō"); 43 if(a[len-1]=='2')printf("ó"); 44 if(a[len-1]=='3')printf("ǒ"); 45 if(a[len-1]=='4')printf("ò"); 46 } 47 else printf("%c",a[i]); 48 } 49 printf("\n"); 50 } 51 else if(ee) { 52 for(int i=0;i<len-1;i++) { 53 if(a[i]=='v')a[i]='u'; 54 } 55 for(int i=0;i<len-1;i++) { 56 if(a[i]=='e') { 57 if(a[len-1]=='1')printf("ē"); 58 if(a[len-1]=='2')printf("é"); 59 if(a[len-1]=='3')printf("ě"); 60 if(a[len-1]=='4')printf("è"); 61 } 62 else printf("%c",a[i]); 63 } 64 printf("\n"); 65 } 66 else if(ii&&!uu) { 67 for(int i=0;i<len-1;i++) { 68 if(a[i]=='i') { 69 if(a[len-1]=='1')printf("ī"); 70 if(a[len-1]=='2')printf("í"); 71 if(a[len-1]=='3')printf("ǐ"); 72 if(a[len-1]=='4')printf("ì"); 73 } 74 else printf("%c",a[i]); 75 } 76 printf("\n"); 77 } 78 else if(uu&&!ii) { 79 for(int i=0;i<len-1;i++) { 80 if(a[i]=='u') { 81 if(a[len-1]=='1')printf("ū"); 82 if(a[len-1]=='2')printf("ú"); 83 if(a[len-1]=='3')printf("ǔ"); 84 if(a[len-1]=='4')printf("ù"); 85 } 86 else printf("%c",a[i]); 87 } 88 printf("\n"); 89 } 90 else if(uu&&ii) { 91 int post1=0; 92 int post2=0; 93 for(int i=0;i<len-1;i++)if(a[i]=='u')post1=i; 94 for(int i=0;i<len-1;i++)if(a[i]=='i')post2=i; 95 if(post1<post2) { 96 for(int i=0;i<len-1;i++) { 97 if(a[i]=='i') { 98 if(a[len-1]=='1')printf("ī"); 99 if(a[len-1]=='2')printf("í"); 100 if(a[len-1]=='3')printf("ǐ"); 101 if(a[len-1]=='4')printf("ì"); 102 } 103 else printf("%c",a[i]); 104 } 105 printf("\n"); 106 } 107 else { 108 for(int i=0;i<len-1;i++) { 109 if(a[i]=='u') { 110 if(a[len-1]=='1')printf("ū"); 111 if(a[len-1]=='2')printf("ú"); 112 if(a[len-1]=='3')printf("ǔ"); 113 if(a[len-1]=='4')printf("ù"); 114 } 115 else printf("%c",a[i]); 116 } 117 printf("\n"); 118 } 119 } 120 else if(vv&&!ee) { 121 for(int i=0;i<len-1;i++) { 122 if(a[i]=='v') { 123 if(a[len-1]=='1')printf("ǖ"); 124 if(a[len-1]=='2')printf("ǘ"); 125 if(a[len-1]=='3')printf("ǚ"); 126 if(a[len-1]=='4')printf("ǜ"); 127 } 128 else printf("%c",a[i]); 129 } 130 printf("\n"); 131 } 132 } 133 } 134 else printf("Case %d: %s\n",_++,a); 135 } 136 }
F.按照r排序,贪心从每一个需要安放灯的r到l开始放就行,这样能保证当前区间与后面的区间相交的部分最大。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Node { 5 int l, r, t; 6 }Node; 7 8 const int maxn = 1010; 9 int n, m, k; 10 bool vis[maxn]; 11 Node p[maxn]; 12 13 bool cmp(Node a, Node b) { 14 return a.r < b.r; 15 } 16 17 int gao() { 18 int ret = 0; 19 for(int i = 0; i < m; i++) { 20 if(p[i].r - p[i].l + 1 < p[i].t) return -1; 21 int cnt = 0; 22 for(int j = p[i].l; j <= p[i].r; j++) cnt += vis[j]; 23 if(cnt >= p[i].t) continue; 24 for(int j = p[i].r; j >= p[i].l; j--) { 25 if(!vis[j]) { 26 vis[j] = 1; 27 cnt++; 28 ret++; 29 if(cnt == p[i].t) break; 30 } 31 } 32 } 33 return ret; 34 } 35 36 int main() { 37 // freopen("in", "r", stdin); 38 int T, _ = 1; 39 int l, r, t; 40 scanf("%d", &T); 41 while(T--) { 42 scanf("%d%d%d",&n,&m,&k); 43 memset(vis, 0, sizeof(vis)); 44 int pos = 0; 45 for(int i = 0; i < k; i++) { 46 scanf("%d", &pos); 47 vis[pos] = 1; 48 } 49 for(int i = 0; i < m; i++) { 50 scanf("%d%d%d",&l,&r,&t); 51 p[i] = Node{l, r, t}; 52 } 53 sort(p, p+m, cmp); 54 55 printf("Case %d: %d\n", _++, gao()); 56 } 57 return 0; 58 }
G.二分k,更新花费后最小生成树,求是否mst<=M。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { 5 int u, v, t, f; double cost; 6 bool operator<(const Edge a)const { 7 return cost < a.cost; 8 } 9 }Edge; 10 11 const int maxn = 100100; 12 const double eps = 1e-11; 13 int n, m; 14 Edge edge[maxn]; 15 int pre[maxn]; 16 double M; 17 18 bool cmp(Edge a, Edge b) { return a.cost < b.cost; } 19 20 int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } 21 22 bool ok(double k) { 23 double cost = .0; 24 for(int i = 1; i <= n; i++) pre[i] = i; 25 for(int i = 1; i <= m; i++) { 26 if(edge[i].f) edge[i].cost = edge[i].t * 1.0 * k; 27 else edge[i].cost = edge[i].t; 28 } 29 sort(edge+1, edge+m+1); 30 for(int i = 1; i <= m; i++) { 31 int u = edge[i].u, v = edge[i].v; 32 int pu = find(u), pv = find(v); 33 if(pu == pv) continue; 34 pre[pu] = pv; 35 cost += edge[i].cost; 36 } 37 return cost <= M; 38 } 39 40 inline bool scan_d(int &num) { 41 char in;bool IsN=false; 42 in=getchar(); 43 if(in==EOF) return false; 44 while(in!='-'&&(in<'0'||in>'9')) in=getchar(); 45 if(in=='-'){ IsN=true;num=0;} 46 else num=in-'0'; 47 while(in=getchar(),in>='0'&&in<='9'){ 48 num*=10,num+=in-'0'; 49 } 50 if(IsN) num=-num; 51 return true; 52 } 53 54 inline bool scan_lf(double &num) { 55 char in;double Dec=0.1; 56 bool IsN=false,IsD=false; 57 in=getchar(); 58 if(in==EOF) return false; 59 while(in!='-'&&in!='.'&&(in<'0'||in>'9')) 60 in=getchar(); 61 if(in=='-'){IsN=true;num=0;} 62 else if(in=='.'){IsD=true;num=0;} 63 else num=in-'0'; 64 if(!IsD){ 65 while(in=getchar(),in>='0'&&in<='9'){ 66 num*=10;num+=in-'0';} 67 } 68 if(in!='.'){ 69 if(IsN) num=-num; 70 return true; 71 }else{ 72 while(in=getchar(),in>='0'&&in<='9'){ 73 num+=Dec*(in-'0');Dec*=0.1; 74 } 75 } 76 if(IsN) num=-num; 77 return true; 78 } 79 80 int main() { 81 // freopen("in", "r", stdin); 82 while(~scanf("%d",&n)) { 83 scan_d(m); 84 scan_lf(M); 85 for(int i = 1; i <= m; i++) { 86 scan_d(edge[i].u); 87 scan_d(edge[i].v); 88 scan_d(edge[i].t); 89 scan_d(edge[i].f); 90 } 91 double lo = 1, hi = 1e15; 92 for(int i = 0; i < 100; i++) { 93 double mid = (lo + hi) / 2; 94 if(ok(mid)) lo = mid; 95 else hi = mid; 96 } 97 printf("%.10f\n", lo); 98 } 99 return 0; 100 }
C.n m <= 8,暴力回溯就行。注意走到一个点要让它相邻的四个点都不能走过,否则可以从之前的某个点直接到那个点。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 11; 5 int n, m; 6 int ex, ey, k; 7 int G[maxn][maxn]; 8 9 int dfs(int x,int y,int cnt) { 10 if(x==ex&&y==ey) { 11 if(cnt>=k) { 12 G[x][y] = 1; 13 return 1; 14 } 15 G[x][y] = 0; 16 return 0; 17 } 18 if(x==0||y==0||x>n||y>m) return 0; 19 G[x][y]=-1; 20 if(G[x+1][y]!=-1&&G[x+2][y]!=-1&&G[x+1][y+1]!=-1&&G[x+1][y-1]!=-1&&dfs(x+1,y,cnt+1)) { 21 G[x][y] = 1; 22 return 1; 23 } 24 25 if(G[x-1][y]!=-1&&G[x-1][y+1]!=-1&&G[x-1][y-1]!=-1&&G[x-2][y]!=-1&&dfs(x-1,y,cnt+1)) { 26 G[x][y] = 1; 27 return 1; 28 } 29 30 if(G[x][y+1]!=-1&&G[x+1][y+1]!=-1&&G[x-1][y+1]!=-1&&G[x][y+2]!=-1&&dfs(x,y+1,cnt+1)) { 31 G[x][y] = 1; 32 return 1; 33 } 34 35 if(G[x][y-1]!=-1&&G[x+1][y-1]!=-1&&G[x-1][y-1]!=-1&&G[x][y-2]!=-1&&dfs(x,y-1,cnt+1)) { 36 G[x][y] = 1; 37 return 1; 38 } 39 G[x][y] = 0; 40 return 0; 41 } 42 int main() { 43 // freopen("in", "r", stdin); 44 while(~scanf("%d%d%d%d%d",&n,&m,&ex,&ey,&k)) { 45 memset(G,0,sizeof(G)); 46 dfs(1,1,0); 47 for(int i = 1; i <= n; i++) { 48 for(int j = 1; j <= m; j++) { 49 if(G[i][j]) printf("."); 50 else printf("*"); 51 } 52 printf("\n"); 53 } 54 } 55 return 0; 56 }
B.trie+dp,子串都丢到trie上,dp(i)代表字符串在[i,len)的最优秀,枚举字符串的后缀,更新dp,dp(0)为最优解。
记录路径:path(i)代表从左到右遍历到第i个字符的时候,这个字符到path(i)的字符为一个子串。输出的时候,输出i到path(i)的字符,之后输出一个空格就可以了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Node { 5 int id; 6 bool sign; 7 Node* next[27]; 8 Node() { for(int i = 0; i < 26; i++) next[i] = NULL; sign = 0; id = -1; } 9 }Node; 10 const int maxn = 1200500; 11 int n, q; 12 double val[maxn], dp[maxn]; 13 char tmp[5555]; 14 int path[maxn]; 15 16 void insert(Node* rt, char* str, int id) { 17 Node* cur = rt; 18 for(int i = 0; str[i]; i++) { 19 int id = tolower(str[i]) - 'a'; 20 if(cur->next[id] == NULL) cur->next[id] = new Node(); 21 cur = cur->next[id]; 22 } 23 cur->sign = 1; cur->id = id; 24 } 25 26 int main() { 27 // freopen("in", "r", stdin); 28 double x; 29 while(~scanf("%d", &n)) { 30 memset(val, 0, sizeof(val)); 31 Node* rt = new Node(); 32 for(int i = 1; i <= n; i++) { 33 scanf("%s %lf", tmp, &x); 34 insert(rt, tmp, i); 35 int len = strlen(tmp); 36 val[i] = (double)len * len * log(x); 37 } 38 scanf("%d", &q); 39 while(q--) { 40 scanf("%s", tmp); 41 int len = strlen(tmp); 42 memset(dp, 0, sizeof(dp)); 43 for(int i = len - 1; i >= 0; i--) { 44 Node* cur = rt; 45 for(int j = 0; i + j < len; j++) { 46 int id = tolower(tmp[i+j]) - 'a'; 47 if(cur->next[id] == NULL) break; 48 cur = cur->next[id]; 49 if(cur->sign) { 50 if(val[cur->id] + dp[i+j+1] >= dp[i]) { 51 dp[i] = val[cur->id] + dp[i+j+1]; path[i] = i + j + 1; 52 } 53 } 54 else { 55 if(dp[i+j+1] >= dp[i]) { 56 dp[i] = dp[i+j+1]; path[i] = i + j + 1; 57 } 58 } 59 } 60 } 61 printf("%.10f\n", dp[0]); 62 int p = 0; 63 while(p != len) { 64 int nx = path[p]; 65 for(int i = p; i < nx; i++) printf("%c", tmp[i]); 66 printf(" "); 67 p = nx; 68 } 69 printf("\n"); 70 } 71 } 72 return 0; 73 }
I.感觉就是一道很水的题,注意抠细节。