您的位置:首页 > 其它

第一次练习赛解题报告及标程

2014-03-15 12:01 363 查看
  因为实际的课程还没有开始讲,这次的练习赛着重于对上学期C++知识的复习,以及对数据结构课程内容的一些铺垫。主要考查了结构体、指针、预处理等相关知识。以下为简单的题解和标程。

  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

  改编自Magic
Pairs, 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写的渣题解,有不明白的欢迎小窗或邮件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: