第一次练习赛解题报告及标程
2014-03-15 12:01
363 查看
因为实际的课程还没有开始讲,这次的练习赛着重于对上学期C++知识的复习,以及对数据结构课程内容的一些铺垫。主要考查了结构体、指针、预处理等相关知识。以下为简单的题解和标程。
渣诚写的,用了直接选择排序,最常规的写法,不多说了。
我写的,sort排序,用到了运算符重载,C++2课上以后会讲到。具体的可以查阅sort函数用法。
这里放出一个用栈实现的版本,使用了STL。实际大数相加没有这么写的,仅供娱乐。网上相关的代码很多,漂亮的大数模板也很多,可以自行查找学习。
再放一个从我的高精度模板节选的一部分。
渣诚写的,用了指针,写得繁琐了一点,那时渣诚和我都太年轻。
我写的,没用指针,下标为0的行和列起到hash的作用。
E. SubMatrix++
分别是查询子矩阵的和,以及查询子矩阵不同数字的个数。因为当时OJ对测试数据的限定过小,导致这两道题被很多人用O(n)甚至O(n^2)的查询水过去了,没有达到考查预处理的目的。于是第二次练习赛重出了这两道题,并加大了数据量。题解和标程下次放出。
Pairs, CodeChef December Challenge 2013。这道题应该比较水,但是过题数不尽人意。要注意题目安排是随机的,并不是按照难度排序。所有配对减去身价相同的配对就是答案。注意第二轮数据10^5的数据量,需要用O(nlogn)的排序,且配对数达到10^10级别,需要用long long,这是一个小trick。
以上是wjfwzzc写的渣题解,有不明白的欢迎小窗或邮件。
A. Page Turn
签到题,改编自Pages, Codeforces Round #233 (Div. 2) A,太水了不多讲。看下标程可以写得多简洁就好。//by trashLHC #include<cstdio> int main(){ int n,p,k,start,end; while(~scanf("%d%d%d",&n,&p,&k)){ start = 1+ (p-k-1)*((p-k)>0); end = n+(p+k-n)*(!(p+k>n)); if(start!=1) printf("<< "); for(int i=start;i<=end;i++) (i==p)?printf("(%d) ",i):printf("%d ",i); if(end!=n) printf(">>"); printf("\n"); } }
//by wjfwzzc #include<cstdio> #include<algorithm> using namespace std; int main() { int n,p,k; while(~scanf("%d%d%d",&n,&p,&k)) { if(p-k>1) printf("<< "); for(int i=max(1,p-k); i<=min(n,p+k); ++i) printf(i==p?"(%d) ":"%d ",i); if(p+k<n) printf(">>"); putchar('\n'); } }
B. SoRtiNg
考查结构体的运用以及排序,数据量小,O(n^2)排序就可以过。这里分别给出两份标程。渣诚写的,用了直接选择排序,最常规的写法,不多说了。
//by trashLHC #include<iostream> #include<cstdio> #include<fstream> #include<algorithm> using namespace std; typedef struct{ string name; int ID; int AVscore; int GPA; }Student; int main(){ int n; while(cin>>n){ Student s[1001]; for(int i=0;i<n;i++) cin>>s[i].name>>s[i].ID>>s[i].AVscore>>s[i].GPA; for(int i=0;i<n-1;i++) for(int j=0;j<n-i-1;j++){ if(s[j].AVscore<s[j+1].AVscore) swap(s[j],s[j+1]); else if(s[j].AVscore==s[j+1].AVscore){ if(s[j].GPA<s[j+1].GPA) swap(s[j],s[j+1]); else if(s[j].GPA==s[j+1].GPA) if(s[j].ID>s[j+1].ID) swap(s[j],s[j+1]); } } for(int i=0;i<n;i++) cout<<s[i].name<<' '<<s[i].ID<<' '<<s[i].AVscore<<' '<<s[i].GPA<<endl; } return 0; }
我写的,sort排序,用到了运算符重载,C++2课上以后会讲到。具体的可以查阅sort函数用法。
//by wjfwzzc #include<cstdio> #include<algorithm> using namespace std; const int MAXN=1005; struct stu { int score,gpa,num; char name[12]; bool operator<(const stu &b) const { if(score==b.score) { if(gpa==b.gpa) return num<b.num; return gpa>b.gpa; } return score>b.score; } } data[MAXN]; int main() { int n; while(~scanf("%d",&n)) { for(int i=0; i<n; ++i) scanf("%s%d%d%d",data[i].name,&data[i].num,&data[i].score,&data[i].gpa); sort(data,data+n); for(int i=0; i<n; ++i) printf("%s %d %d %d\n",data[i].name,data[i].num,data[i].score,data[i].gpa); } }
C. A+B again
大数相加,很古董的题了……考查数组的理解,以及一定的编码能力;注意一下进位和0即可。//by trashLHC #include<cstdio> #include<cstring> #include<iostream> #include<string> using namespace std; int main() { int t; scanf("%d",&t);getchar(); char a[1111],b[1111],c[1111]; while(t--) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); scanf("%s%s",a,b); int i,l1=strlen(a),l2=strlen(b); for(i=0;i<l1/2;i++) swap(a[i],a[l1-i-1]); for(i=0;i<l2/2;i++) swap(b[i],b[l2-i-1]); for(i=0;i<max(l1,l2);i++) { if(a[i]>='0'&&a[i]<='9') c[i]+=a[i]-'0'; if(b[i]>='0'&&b[i]<='9') c[i]+=b[i]-'0'; c[i+1]+=c[i]/10; c[i]%=10; } if(c[i]==0)i--; for(;i>=0;i--) printf("%c",c[i]+'0'); printf("\n"); } }
这里放出一个用栈实现的版本,使用了STL。实际大数相加没有这么写的,仅供娱乐。网上相关的代码很多,漂亮的大数模板也很多,可以自行查找学习。
//by wjfwzzc #include<cstdio> #include<cstring> #include<stack> using namespace std; const int MAXN=100005; char sta[MAXN],stb[MAXN]; stack<char> sa,sb,ans; int main() { int n; scanf("%d",&n); while(n--) { scanf("%s%s",sta,stb); int la=strlen(sta),lb=strlen(stb); for(int i=0; i<la; ++i) sa.push(sta[i]); for(int i=0; i<lb; ++i) sb.push(stb[i]); int tmp=0; while(!sa.empty()||!sb.empty()) { char ta='0',tb='0'; if(!sa.empty()) { ta=sa.top(); sa.pop(); } if(!sb.empty()) { tb=sb.top(); sb.pop(); } tmp+=ta-'0'+tb-'0'; ans.push(char(tmp%10+'0')); tmp/=10; } if(tmp>0) ans.push(char(tmp+'0')); while(!ans.empty()) { putchar(ans.top()); ans.pop(); } putchar('\n'); } }
再放一个从我的高精度模板节选的一部分。
//by wjfwzzc #include<iostream> #include<string> #include<algorithm> using namespace std; const int ten[4]= {1,10,100,1000}; const int maxl=100005; struct BigNumber { int d[maxl]; BigNumber(string s) { int len=s.size(); d[0]=(len-1)/4+1; for(int i=1; i<maxl; ++i) d[i]=0; for(int i=len-1; i>=0; --i) { int j=(len-i-1)/4+1,k=(len-i-1)%4; d[j]+=ten[k]*(s[i]-'0'); } while(d[0]>1&&d[d[0]]==0) --d[0]; } BigNumber() { *this=BigNumber(string("0")); } string toString() { string s(""); int i,j,tmp=d[d[0]]; for(i=3; i>=1; --i) if(d[d[0]]>=ten[i]) break; for(j=i; j>=0; --j) { s=s+char(tmp/ten[j]+'0'); tmp%=ten[j]; } for(i=d[0]-1; i>0; --i) { tmp=d[i]; for(j=3; j>=0; --j) { s=s+char(tmp/ten[j]+'0'); tmp%=ten[j]; } } return s; } } ; BigNumber operator+(const BigNumber &a,const BigNumber &b) { BigNumber c; c.d[0]=max(a.d[0],b.d[0]); int x=0; for(int i=1; i<=c.d[0]; ++i) { x+=a.d[i]+b.d[i]; c.d[i]=x%10000; x/=10000; } while(x!=0) { c.d[++c.d[0]]=x%10000; x/=10000; } return c; } int main() { int n; string sta,stb; cin>>n; while(n--) { cin>>sta>>stb; BigNumber a(sta),b(stb); cout<<(a+b).toString()<<endl; } }
D. Chem Is A Fourth Try
陈题。矩阵中行或列的交换,希望考查到指针的应用,很可耻地失败了……因为完全可以用一个类似于hash表的方式模拟指针。这里放出两份代码。渣诚写的,用了指针,写得繁琐了一点,那时渣诚和我都太年轻。
//by trashLHC #include<iostream> #include<cstdio> #include<fstream> using namespace std; int n,m,k,*p1[1001],*p2[1001],a,b,*tmp,colS[10001][2],rowS[10001][2],numC,numR; char c; int main() { while(scanf("%d%d%d",&n,&m,&k)!=EOF) { numC=numR=0; for(int i=0;i<n;i++) p1[i]=new int[m]; for(int i=0;i<m;i++) p2[i]=new int ; for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&p1[i][j]); for(int i=0;i<k;i++) { scanf(" %c %d%d",&c,&a,&b); if(c=='R') {rowS[numR][0]=a-1;rowS[numR++][1]=b-1;} else {colS[numC][0]=a-1;colS[numC++][1]=b-1;} } for(int i=0;i<numR;i++) { tmp=p1[rowS[i][0]]; p1[rowS[i][0]]=p1[rowS[i][1]]; p1[rowS[i][1]]=tmp; } for(int i=0;i<n;i++) for(int j=0;j<m;j++) p2[j][i]=p1[i][j]; for(int i=0;i<numC;i++) { tmp=p2[colS[i][0]]; p2[colS[i][0]]=p2[colS[i][1]]; p2[colS[i][1]]=tmp; } for(int i=0;i<n;i++) { for(int j=0;j<m;j++) printf("%d ",p2[j][i]); printf("\n"); } for(int i=0;i<n;i++) delete[] p1[i]; for(int i=0;i<m;i++) delete[] p2[i]; } }
我写的,没用指针,下标为0的行和列起到hash的作用。
//by wjfwzzc #include<cstdio> #include<algorithm> using namespace std; const int MAXN=1005; int g[MAXN][MAXN]; int main() { int n,m,k,p,q; char c; while(~scanf("%d%d%d",&n,&m,&k)) { for(int i=1; i<=n; ++i) g[i][0]=i; for(int i=1; i<=m; ++i) g[0][i]=i; for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) scanf("%d",&g[i][j]); while(k--) { scanf(" %c%d%d",&c,&p,&q); switch(c) { case 'R': swap(g[p][0],g[q][0]); break; case 'C': swap(g[0][p],g[0][q]); break; } } for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) printf("%d ",g[g[i][0]][g[0][j]]); putchar('\n'); } } }
E. SubMatrix++
F. SubMatrix+++++
分别是查询子矩阵的和,以及查询子矩阵不同数字的个数。因为当时OJ对测试数据的限定过小,导致这两道题被很多人用O(n)甚至O(n^2)的查询水过去了,没有达到考查预处理的目的。于是第二次练习赛重出了这两道题,并加大了数据量。题解和标程下次放出。G. Counting Pairs
改编自MagicPairs, CodeChef December Challenge 2013。这道题应该比较水,但是过题数不尽人意。要注意题目安排是随机的,并不是按照难度排序。所有配对减去身价相同的配对就是答案。注意第二轮数据10^5的数据量,需要用O(nlogn)的排序,且配对数达到10^10级别,需要用long long,这是一个小trick。
//by wjfwzzc #include<cstdio> #include<algorithm> using namespace std; const int MAXN=100005; int a[MAXN]; int main() { long long n; while(~scanf("%lld",&n)) { for(int i=0; i<n; ++i) scanf("%d",&a[i]); sort(a,a+n); long long equal=0; for(int i=1; i<n; ++i) { long long cnt=1; while(a[i]==a[i-1]) { ++i; ++cnt; } equal+=cnt*(cnt-1)/2; } printf("%lld\n",n*(n-1)/2-equal); } }
以上是wjfwzzc写的渣题解,有不明白的欢迎小窗或邮件。
相关文章推荐
- 第三次练习赛解题报告及标程
- 第五次练习赛解题报告及标程
- 第六次练习赛解题报告及标程
- 第一次上机赛解题报告及标程
- 第四次练习赛解题报告及标程
- 第一次参加topcoder的感悟和解题报告
- 2011新生练习赛三解题报告
- 一月17日新生冬季练习赛解题报告H.龟兔赛跑
- 2013级数据结构第二次练习赛解题报告
- 第一次小组赛解题报告
- 第二届顶嵌杯决赛解题报告------祭奠我的第一次比赛
- 解题报告——第一次只出现一次的字符
- 期末上机赛解题报告及标程
- 正睿OI noip2017冲刺 第一次考试T2 解题报告
- CCNU 2010新生练习赛1解题报告
- 【作业解答】第一次上机作业解题报告
- 北京航空航天大学2014级C++第一次练习*L题解题报告
- 队内赛我出的一道题附标程、数据与解题报告
- 【九度】2014年王道论坛研究生机试练习赛第三场解题报告
- Hihocoder [Offer收割]编程练习赛70 解题报告 By cellur925