紫书第四章 函数和递归
例题
组合数
编写函数求 C(m,n) = n!/m!(n-m)! ,其中 m<=n<=25,例如,n=25,m=12时答案为5200300
#include <iostream> using namespace std; long long C(int n,int m) { if(m < n-m) m = n-m; //约掉较大的那个数 long long ans = 1; for(int i = m+1; i <= n; ++i) ans *= i; for(int i = 1; i <= n-m; ++i) //巧妙的n-m,当n-m > m时,约掉n-m,需要除m!,故此时n-m = m ans /= i; return ans; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { printf("%lld\n",C(n,m)); } return 0; }
古老的密码(uva1339)
题解:密码以某种转换规则转换且打乱顺序,要求我们判断此字符串是否为密码根据某种规则转换而来
其实非常简单,既然是根据某种规则转换而来,那么其中某个字符的出现次数都是一定的,
比如说:原串:j有11个 b有3个 加密后j边城a, b变成c,那么加密后a仍有11个,c仍有3个
我们只需要对原串和加密串的各字符进行排序即可,若相同则YES,不同则NO
for(int i = 0; i < n; ++i) { cnt1[s1[i]]++; cnt2[s2[i]]++; } sort(cnt1.begin(),cnt1.end()); sort(cnt2.begin(),cnt2.end());
完整代码
#include <iostream> #include <algorithm> #include <vector> #define LOCA using namespace std; int main() { string s1; string s2; vector<int> cnt1(150,0); vector<int> cnt2(150,0); #ifdef LOCAL freopen("data.in","r",stdin); #endif // LOCAL while(cin >> s1 >> s2) { int n = s1.size(); fill(cnt1.begin(),cnt1.end(),0); fill(cnt2.begin(),cnt2.end(),0); for(int i = 0; i < n; ++i) { cnt1[s1[i]]++; cnt2[s2[i]]++; } sort(cnt1.begin(),cnt1.end()); sort(cnt2.begin(),cnt2.end()); bool flag = true; for(int i = 0; i < 150 && flag; ++i) { if(cnt1[i] != cnt2[i]) flag = false; } cout << (flag?"YES":"NO") << endl; } return 0; }
刽子手游戏(uva489)
题解:简单的暴力即可
#include <iostream> #include <cstdio> #include <set> #define LOCAL //注意每个字符错误只能记一次,但曾经正确的答案反复猜也是错 using namespace std; int main() { int rd; set<char> flag; string answer; string guess; int chance; #ifdef LOCAL freopen("data.in","r",stdin); #endif // LOCAL while(scanf("%d",&rd) && rd != -1) { cin >> answer >> guess; printf("Round %d\n",rd); chance = 7; flag.clear(); int cnt = answer.size(); for(int i = 0; i < cnt; ++i) flag.insert(answer[i]); int len = guess.size(); for(int i = 0; i < len; ++i) { if(flag.erase(guess[i]) == 0){ chance--; } if(flag.empty() || chance == 0) break; } if(chance == 0) printf("You lose."); else if(flag.empty()) printf("You win."); else printf("You chickened out."); putchar('\n'); } return 0; }
#include <bits/stdc++.h> #define LOCA const int maxn = 100; using namespace std; char s[maxn],s2[maxn]; int le = 0,chance = 0; int win,lose; void guess(char ch) { int bad = 1; for(int i = 0; i < strlen(s); ++i) if(s[i] == ch) { bad = 0; s[i] = ' '; le--; } if(bad) chance--; if(!le) win = 1; else if(!chance) lose = 1; } int main() { int rd; #ifdef LOCAL freopen("data.in","r",stdin); #endif // LOCAL while(scanf("%d",&rd) && rd != -1) { scanf("%s%s",s,s2); printf("Round %d\n",rd); win = lose = 0; le = strlen(s); chance = 7; int len = strlen(s2); for(int i = 0; i < len; ++i) { guess(s2[i]); if(win || lose) break; } if(win) printf("You win.\n"); else if(lose) printf("You lose.\n"); else printf("You chickened out.\n"); } return 0; }
救济金发放(UVA133)
题解:环。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n,k,m; bool vis[22]; int guess(int p,int mod,int t) { while(t--) { do{p = (p+mod-1+n)%n+1;}while(vis[p]); } return p; } int main() { while(~scanf("%d%d%d",&n,&k,&m) && n) { memset(vis,false,sizeof(vis)); int left = n; int p1 = 0, p2 = n+1; while(left) { p1 = guess(p1,1,k); p2 = guess(p2,-1,m); vis[p1] = vis[p2] = true; printf("%3d",p1); left--; if(p1 != p2) { printf("%3d",p2); left--; } if(left != 0) printf(","); } putchar('\n'); } return 0; }
信息解码(UVA213)
题解:
#include <bits/stdc++.h> #define LOCAL using namespace std; char code[8][1<<8]; char readchar() { int ch; while((ch = getchar()) == '\n' || ch == '\r'); return ch; } int readcode() { memset(code,0,sizeof(code)); code[1][0] = readchar(); //因为第二个样例后会有回车需要readchar if(code[1][0] == EOF) return 0; int ch; for(int i = 2; i <= 7; i++) for(int j = 0; j < (1<<i)-1; j++) { ch = getchar(); if(ch == EOF) return 0; if(ch == '\n' || ch == '\r') return 1; code[i][j] = ch; } return 1; } int readint(int len) { int v = 0; while(len--) { v = v*2+( readchar()-'0' ); } return v; } int main() { #ifdef LOCAL freopen("data.in","r",stdin); #endif // LOCAL while(readcode()) { int cnt = 0; for(;;) { int len = readint(3); if(len == 0) break; for(;;) { int t = readint(len); if(t == (1 << len)-1) break; putchar(code[len][t]); } } putchar('\n'); } return 0; }
追踪电子表格中的单元格(UVA512)
方法一:利用另一个表完成主表的插入删除
#include <iostream> #include <cstdio> #include <cstring> #define BIG 1000 const int maxn = 100; using namespace std; int d[maxn][maxn],d2[maxn][maxn],ans[maxn][maxn],r,c; int cols[maxn]; void Copy(char type,int p,int q) { if(type == 'R'){ for(int i = 1; i <= c; ++i) d[p][i] = d2[q][i]; } else if(type == 'C') { for(int i = 1; i <= r; ++i) d[i][p] = d2[i][q]; } } void Dele(char type) { memcpy(d2,d,sizeof(d)); int n = type=='R'?r:c; int cnt = 0; for(int i = 1; i <= n; ++i) { if(!cols[i]) Copy(type,++cnt,i); } if(type == 'R') r = cnt; else c = cnt; } void Inse(char type) { memcpy(d2,d,sizeof(d)); int cnt = 0; int n = type=='R'?r:c; for(int i = 1; i <= n; ++i) { if(cols[i]) Copy(type,++cnt,0); Copy(type,++cnt,i); } if(type == 'R') r = cnt; else c = cnt; } int main() { int kase = 0; while(cin >> r >> c && r) { int n; string cmd; cin >> n; for(int i = 1; i <= r; ++i) for(int j = 1; j <= c; ++j) d[i][j] = i*BIG+j; while(n--) { memset(cols,0,sizeof(cols)); cin >> cmd; if(cmd[0] == 'E'){ int r1,c1,r2,c2; cin >> r1 >> c1 >> r2 >> c2; swap(d[r1][c1],d[r2][c2]); } else{ int a,x; cin >> a; for(int i = 0; i < a; ++i) { cin >> x; cols[x] = 1; } if(cmd[0] == 'D') Dele(cmd[1]); else Inse(cmd[1]); } } memset(ans,0,sizeof(ans)); for(int i = 1; i <= r; ++i) for(int j = 1; j <= c; ++j) ans[d[i][j]/BIG][d[i][j]%BIG] = i*BIG+j; if(kase > 0) cout << endl; ++kase; cout << "Spreadsheet #" << kase << endl; cin >> n; while(n--) { int x,y; cin >> x >> y; printf("Cell data in (%d,%d) ",x,y); if(ans[x][y] == 0) printf("GONE"); else printf("moved to (%d,%d)",ans[x][y]/BIG,ans[x][y]%BIG); putchar('\n'); } } return 0; }
方法二:保存操作,对每个查询的位置推算操作后的位置
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 1000; int n; struct Command{ string c; int r1,c1,r2,c2; int a,x[20]; }cmd[maxn]; bool simulate(int &x,int &y) { int dr = 0, dc = 0; for(int i = 0; i < n; ++i) { dr = 0,dc = 0; if(cmd[i].c[0] == 'E') { if(cmd[i].r1 == x && cmd[i].c1 == y ) { x = cmd[i].r2; y = cmd[i].c2; } else if(cmd[i].r2 == x && cmd[i].c2 == y) { x = cmd[i].r1; y = cmd[i].c1; } } else { for(int j = 0; j < cmd[i].a; ++j) { if(cmd[i].c[0] == 'I'){ if(cmd[i].c[1] == 'R' && cmd[i].x[j] <= x) dr++; else if(cmd[i].c[1] == 'C' && cmd[i].x[j] <= y) dc++; } if(cmd[i].c[0] == 'D'){ if(cmd[i].c[1] == 'R' && cmd[i].x[j] < x) dr--; else if(cmd[i].c[1] == 'C' && cmd[i].x[j] < y) dc--; else if(cmd[i].c[1] == 'R' && cmd[i].x[j] == x) return false; else if(cmd[i].c[1] == 'C' && cmd[i].x[j] == y) return false; } } x += dr; y += dc; } } return true; } int main() { int r,c,kase = 0; while(cin >> r >> c && r) { cin >> n; for(int i = 0; i < n; ++i) { cin >> cmd[i].c; if(cmd[i].c[0] == 'E') { cin >> cmd[i].r1 >> cmd[i].c1 >> cmd[i].r2 >> cmd[i].c2; } else { cin >> cmd[i].a; for(int j = 0; j < cmd[i].a; ++j) cin >> cmd[i].x[j]; } } if(kase != 0) cout << endl; printf("Spreadsheet #%d\n",++kase); int k; cin >> k; while(k--) { int x,y; cin >> x >> y; printf("Cell data in (%d,%d) ",x,y); if(!simulate(x,y)) printf("GONE"); else printf("moved to (%d,%d)",x,y); putchar('\n'); } } return 0; }
师兄帮帮忙(UVA124)
用太多cout会超时:
#include <cstdio> #include <iostream> #include <vector> #include <algorithm> #define EPS 1e-6 using namespace std; vector<string> sid; vector<int> cid; vector<string> name; vector<vector<int>> scores; //五门成绩,语数英编程和总分 int menu() { cout << "Welcome to Student Performance Management System (SPMS)." << endl; cout << endl; cout << "1 - Add" << endl; cout << "2 - Remove" << endl; cout << "3 - Query" << endl; cout << "4 - Show ranking" << endl; cout << "5 - Show Statistics" << endl; cout << "0 - Exit" << endl; cout << endl; int n; cin >> n; return n; } void add() { string si,na; int ci,grade[5]; cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl; while(cin >> si && si != "0") { cin >> ci >> na >> grade[0] >> grade[1] >> grade[2] >> grade[3]; if(find(sid.begin(),sid.end(),si) != sid.end()){ cout << "Duplicated SID." << endl; cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl; continue; } grade[4] = grade[0]+grade[1]+grade[2]+grade[3]; sid.push_back(si); cid.push_back(ci); name.push_back(na); scores.push_back(vector<int>(grade,grade+5)); cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl; } /*for(int i = 0; i < sid.size(); ++i) { cout << sid[i] << " " << cid[i] << " " << name[i] << " " ; for(int j = 0; j < 5; ++j) cout << scores[i][j] << " "; cout << endl; }*/ } void remve() { string t; cout << "Please enter SID or name. Enter 0 to finish." << endl; while(cin >> t && t != "0") { int n = sid.size(),cnt = 0; for(int i = 0; i < n; ++i) { if(sid[i] == t || name[i] == t) { sid.erase(sid.begin()+i); cid.erase(cid.begin()+i); name.erase(name.begin()+i); scores.erase(scores.begin()+i); cnt++; } } cout << cnt << " student(s) removed." << endl; cout << "Please enter SID or name. Enter 0 to finish." << endl; } } int rak(int i) { int s = scores[i][4]; int rk = count_if(scores.begin(),scores.end(),[s](vector<int> a){ return a[4] > s; } ); return rk+1; } void showRank() { string t; int n = sid.size(); cout << "Please enter SID or name. Enter 0 to finish." << endl; while(cin >> t && t != "0") { for(int i = 0; i < n; ++i) { if(sid[i] == t || name[i] == t) { int rk = rak(i); cout << rk << " " << sid[i] << " " << cid[i] << " "<< name[i] << " "; for(int j = 0; j < 5; ++j) cout << scores[i][j] << " "; printf("%.2lf",(double)scores[i][4]/4+EPS); cout << endl; } } cout << "Please enter SID or name. Enter 0 to finish." << endl; } } void joke() { cout << "Showing the ranklist hurts students’ self-esteem. Don’t do that." << endl; } void showSta() { cout << "Please enter class ID, 0 for the whole statistics." << endl; int c; cin >> c; int n = sid.size(); int p[4] = {0}; //各科通过人数 int f[4] = {0}; //各科挂科人数 int s[4] = {0}; //四科总分 int allp[5] = {0}; for(int i = 0; i < n; ++i) { if(c == 0 || c == cid[i]) { int cnt = 0; int pc = 0; for(int j = 0; j < 4; ++j) { s[j] += scores[i][j]; if(scores[i][j] >= 60) p[j]++,pc++; else f[j]++; } for(int j = pc; j > 0; --j) allp[j]++; if(pc == 0) allp[0]++; } } cout << "Chinese" << endl; cout << "Average Score: "; printf("%.2lf\n",(double)s[0]/(p[0]+f[0])); cout << "Number of passed students: "<< p[0] << endl; cout << "Number of failed students: "<< f[0] << endl << endl; cout << "Mathematics" << endl; cout << "Average Score: "; printf("%.2lf\n",(double)s[1]/(p[1]+f[1])); cout << "Number of passed students: "<< p[1] << endl; cout << "Number of failed students: "<< f[1] << endl << endl; cout << "English" << endl; cout << "Average Score: "; printf("%.2lf\n",(double)s[2]/(p[2]+f[2])); cout << "Number of passed students: "<< p[2] << endl; cout << "Number of failed students: "<< f[2] << endl << endl; cout << "Programming" << endl; cout << "Average Score: "; printf("%.2lf\n",(double)s[3]/(p[3]+f[3])); cout << "Number of passed students: "<< p[3] << endl; cout << "Number of failed students: "<< f[3] << endl << endl; cout << "Overall:" << endl; cout << "Number of students who passed all subjects: "<< allp[4] << endl; cout << "Number of students who passed 3 or more subjects: " << allp[3] << endl; cout << "Number of students who passed 2 or more subjects: " << allp[2] << endl; cout << "Number of students who passed 1 or more subjects: " << allp[1] << endl; cout << "Number of students who failed all subjects: " << allp[0] << endl << endl; } int main() { freopen("data.in","r",stdin); int choice; while((choice = menu())) { switch(choice) { case 1:add(); break; case 2:remve(); break; case 3:showRank(); break; case 4:joke(); break; case 5:showSta(); break; } } return 0; }
优化:
#include <bits/stdc++.h> #define LOCAL #define maxn 1000 #define maxl 100 #define EPS 1e-6 int n = 0; char sid[maxn][maxl]; int cid[maxn]; char name[maxn][maxl]; int score[maxn][5]; //第五个记录总分 int removed[maxn] = {0}; using namespace std; int menu() { int choice; printf("Welcome to Student Performance Management System (SPMS).\n"); printf("\n"); printf("1 - Add\n"); printf("2 - Remove\n"); printf("3 - Query\n"); printf("4 - Show ranking\n"); printf("5 - Show Statistics\n"); printf("0 - Exit\n"); printf("\n"); scanf("%d",&choice); return choice; } bool finded() { for(int i = 0; i < n; i++) if(!removed[i] && strcmp(sid[i],sid[n]) == 0 ) return true; return false; } void add() { for(;;) { printf("Please enter the SID, CID, name and four scores. Enter 0 to finish.\n"); scanf("%s",sid[n]); if(strcmp(sid[n],"0") == 0) break; scanf("%d%s%d%d%d%d",&cid[n],name[n],&score[n][0],&score[n][1],&score[n][2],&score[n][3]); if(!finded()) { score[n][4] = score[n][0]+score[n][1]+score[n][2]+score[n][3]; n++; } else printf("Duplicated SID.\n"); } } int ranks(int index) { int r = 1; for(int i = 0; i < n; i++) if(!removed[i] && score[i][4] > score[index][4]) r++; return r; } void DQ(int isq) { char s[maxl]; for(;;) { int r = 0; printf("Please enter SID or name. Enter 0 to finish.\n"); scanf("%s",s); if(strcmp(s,"0") == 0) break; for(int i = 0; i < n; i++) if(!removed[i]) { if(strcmp(s,sid[i]) == 0 || strcmp(s,name[i]) == 0){ if(isq){ printf("%d %s %d %s %d %d %d %d %d %.2f\n",ranks(i),sid[i],cid[i],name[i],score[i][0],score[i][1],score[i][2], score[i][3],score[i][4],(double)score[i][4]/4+EPS); } else { removed[i] = 1; r++; } } } if(!isq) printf("%d student(s) removed.\n",r); } } const char course[][18] = {"Chinese","Mathematics","English","Programming"}; int cnt[5]; //全过、过3、过2、过1、全没 void analyize(int c) { memset(cnt,0,sizeof(cnt)); for(int i = 0; i < n; i++) if(!removed[i] && (cid[i] == c || c == 0)) { int flag = 0; for(int j = 0; j < 4; j++) if(score[i][j] >= 60) flag++; if(flag == 4) cnt[0]++; else if(flag == 3) cnt[1]++; else if(flag == 2) cnt[2]++; else if(flag == 1) cnt[3]++; else cnt[4]++; } } double analyize_ave(int c,int index,int &passed,int &failed) { double sum = 0, ave; passed = failed = 0; for(int i = 0; i < n; i++) if(!removed[i] && (c == 0 || c == cid[i])) { if(score[i][index] >= 60) passed++; else failed++; sum += score[i][index]; } if(passed+failed == 0) return 0; ave = (double)sum/(double)(passed+failed); return ave; } void show() { int mod; printf("Please enter class ID, 0 for the whole statistics.\n"); scanf("%d",&mod); for(int i = 0; i < 4; i++) { int passed,failed; double ave = analyize_ave(mod,i,passed,failed); printf("%s\n",course[i]); printf("Average Score: %.2f\n", ave+EPS); printf("Number of passed students: %d\n", passed); printf("Number of failed students: %d\n", failed); printf("\n"); } analyize(mod); printf("Overall:\n"); printf("Number of students who passed all subjects: %d\n", cnt[0]); printf("Number of students who passed 3 or more subjects: %d\n", cnt[0]+cnt[1]); printf("Number of students who passed 2 or more subjects: %d\n", cnt[0]+cnt[1]+cnt[2]); printf("Number of students who passed 1 or more subjects: %d\n", cnt[0]+cnt[1]+cnt[2]+cnt[3]); printf("Number of students who failed all subjects: %d\n", cnt[4]); printf("\n"); } int main() { int choice; #ifdef LOCAL freopen("data.in","r",stdin); #endif // LOCAL while( (choice = menu()) != 0 ) { switch(choice) { case 1:add();break; case 2:DQ(0);break; case 3:DQ(1);break; case 4:printf("Showing the ranklist hurts students' self-esteem. Don't do that.\n");break; case 5:show();break; } } return 0; }
习题
象棋(UVA1589)
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; int board[12][10]; //用于标记位置上是否有棋子,判断是否蹩脚马 int dir[4][2] = {1,0,-1,0,0,1,0,-1}; //黑将的四个走法 int hdir[8][2] = { {-2,1},{-2,-1},{2,1},{2,-1},{-1,2},{1,2},{-1,-2},{1,-2} }; struct Pos{ char type; int x; int y; Pos(char t,int xx,int yy):type(t),x(xx),y(yy) {} }; bool check(bool isG,int x,int y) //只有黑帅需要移动故我们只判断黑帅即可 { if(isG) return (y >= 4 && y <= 6) && (x >= 1 && x <= 3); else return (y >= 1 && y <= 9) && (x >= 1 && x <= 10); } int vn(int px,int py,int x) //统计竖直方向与黑帅之间的棋子数 { int cnt = 0; //找出上方与下方的棋子 int high = max(px,x); int low = min(px,x); for(low += 1; low < high; ++low) if(board[low][py]) cnt++; return cnt; } int hn(int px,int py,int y) //统计水平方向与黑帅之间的棋子数 { int cnt = 0; //找出左方与右方的棋子 int low = min(py,y); int high = max(py,y); for(low += 1; low < high; ++low) if(board[px][low]) cnt++; return cnt; } int main() { //freopen("data.in","r",stdin); int n,px,py; while(~scanf("%d%d%d",&n,&px,&py) && n && px && py) { char type[10]; int tx,ty; memset(board,0,sizeof(board)); vector<Pos> pv; while(n--) { scanf("%s%d%d",type,&tx,&ty); board[tx][ty] = 1; pv.push_back(Pos(type[0],tx,ty)); } bool ans = true; //能否将军 for(int i = 0; i < 4; ++i) { tx = px+dir[i][0],ty = py+dir[i][1]; //帅的各种走法 bool live = true; //只要有一种活下就非将军 if(check(true,tx,ty)) { for(Pos t : pv){ if(t.x == tx && t.y == ty) continue; //被帅吃了 if(t.type == 'G' && t.y == ty && vn(tx,ty,t.x) == 0){ //红将军与黑帅中间无棋子,将军 live = false; break; } else if(t.type == 'R' && ( t.y == ty && vn(tx,ty,t.x) == 0 || t.x == tx && hn(tx,ty,t.y)==0 )){ live = false; break; } else if(t.type == 'C' && ( t.y == ty && vn(tx,ty,t.x) == 1 || t.x == tx && hn(tx,ty,t.y)==1) ){ live = false; break; } else if(t.type == 'H'){ for(int j = 0; j < 8; ++j) { int hx = t.x+hdir[j][0]/2, hy = t.y+hdir[j][1]/2; if(!check(false,hx,hy)) continue; //陷阱:马会向前走一步再侧走故此步不规范马也不可侧走 if(board[hx][hy]) continue; int fx = t.x+hdir[j][0],fy = t.y+hdir[j][1]; if(fx == tx && fy == ty) { live = false; break; } } } if(live == false){ break; } } } if(check(true,tx,ty) && live){ ans = false; break; } } printf("%s\n",ans?"YES":"NO"); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!