2013 SWJTU ACM 新秀杯资格赛参考题解
A题:a+b问题,很简单,不解释什么了。
代码:
#include<algorithm> #include<stdio.h> #include<iostream> #include<string.h> using namespace std; int main() { int a,b; while(cin>>a>>b)cout<<a+b<<endl; return 0; }
B题:输入一个整数n(n<=50),输出第n个斐波那契数。题目比较简单,开一个a[100],然后对于第i个斐波那契数a[i]=a[i-1]+a[i-2],递推一下,
很快就可以把前50个斐波那契数找出来,然后对于每一组输入,直接输出答案。注意使用64位的整数,可以定义成 long long。
代码:
#include<algorithm> #include<stdio.h> #include<iostream> #include<string.h> using namespace std; typedef long long ll; ll a[100]; int main() { a[1]=1; a[2]=2; for(ll i=3;i<=50;i++)a[i]=a[i-1]+a[i-2]; ll n; while(cin>>n)cout<<a[n]<<endl; return 0; }
C 题:已知有n个顶点,m条边,问再加多少条边可以使所有的点连在一起。一看就是并查集裸题,连接n个点,有ans=n-1条边是必须的,将m条边用并查集判断
是否在同一个集合里面,假设不在,就合并,同时ans--,最后的ans就是答案。
代码:
#include<algorithm> #include<stdio.h> #include<iostream> #include<string.h> using namespace std; int fa[300]; int find(int x) { if(fa[x]!=x)fa[x]=find(fa[x]); return fa[x]; } int main() { int n,i,j,k,m; while(cin>>n>>m) { k=n-1; for(i=1;i<=n;i++)fa[i]=i; while(m--) { cin>>i>>j; i=find(i); j=find(j); if(i!=j) { fa[i]=j; k--; } } cout<<k<<endl; } return 0; }
D题:给定n个点的经纬度,以及地球的半径,计算某两个顶点之间的直线距离的最小值。
这道题的关键问题是一直两个点的经纬度,计算这两个点之间的题目要求的距离,
地球半径已知,可以先考虑计算地球球心与两个点连线之间的夹角,只要夹角搞
出来,答案自然就出来了,具体细节见代码。
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<iomanip> #include<string> #include<string.h> using namespace std; inline double Min(double a,double b){return a>b?b:a;} const double pi=acos(-1.0); struct node { double j, w; }hehe[105]; #define r 6370 double change(double x) { return x/360.0; } double get_distance(node a,node b) { return r*2*sin((acos(cos(change(a.j)*2*pi)*cos(change(b.j)*2*pi)*cos(change(a.w)*2*pi-change(b.w)*2*pi)+ sin(change(a.j)*2*pi)*sin(change(b.j)*2*pi)))/2); } int main(){ int n,i ,j ; while(~scanf("%d",&n)) { for(i = 0; i < n; i++) { scanf("%lf %lf",&hehe[i].w,&hehe[i].j); } double ans = 100000000.0; for(i = 0; i<n ;i++) for(j = i+1; j< n; j++) { ans = Min(ans, get_distance(hehe[i],hehe[j]) ); } printf("%.2lf\n",ans); } return 0; }
E题:给定一个一个式子,计算0到1之间的定积分,貌似积分函数是可以找到原函数的,不过自己数学功底忘光了,想了好久也找出来,
看到貌似好多人找出了公式,在此深深地膜拜一下,没找出公式,便想着看怎么用数值计算的方法把它搞出来,结果输出了非数字的东西,
观察了不少时间,还是没想明白为什么,后来发现假设自变量等于1,被积函数分母等于0,于是自己把积分区间变成[eps,1-eps],然后
计算出来,发现第一组样例会出现-0.00,然后处理一下就1Y了。
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<iomanip> #include<string> #include<string.h> using namespace std; const double eps=1e-5; double A,B; double fun(double x) { return (pow(x,B)-pow(x,A))/log(x); } double fun1(double a,double b) { double p=eps+1.0; double t,h=b-a,t1=(fun(a)+fun(b))*h/2; while(p>=eps) { double s=0; for(double k=a+h/2;k<=b;k+=h)s+=fun(k); t=t1/2+h*s/2; p=fabs(t-t1);t1=t; h/=2; } return t; } int main() { while(cin>>A>>B) { double ans=fun1(eps,1.0-eps); char str[10]; sprintf(str,"%.2lf",ans); if(strcmp(str,"-0.00")==0)strcpy(str,"0.00"); printf("%s\n",str); } return 0; }
F题:给定一个长度为n的序列a[1],a[2],,,,,,,a[n],输出n个数,对于a[i],输出序列中其他n-1个数可以整除a[i]的整数的个数。
首先,由于题目输入输出比较多,因此可以考虑采用读写外挂读入,由于序列数据范围为1000000,可以开一个1000000的数组,标记每一个数的出现次数,然后枚举每一个出现过的数,然后叠加到他的倍数上面,最后减一输出即可。
代码:
#include<algorithm> #include<stdio.h> #include<iostream> #include<string.h> using namespace std; const int maxn=1000100; int a[maxn],b[maxn],c[maxn]; int fun() { char ch; int flag=1,a=0; while(ch=getchar()) { if((ch>='0'&&ch<='9')||ch=='-')break; } if(ch=='-')flag=-1; else a=ch-'0'; while(ch=getchar()) { if(ch>='0'&&ch<='9')a=10*a+ch-'0'; else break; } return flag*a; } int main() { int i,j,k,m,n,T,t; T=fun(); for(t=1;t<=T;t++) { n=fun(); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); int pp=-1; for(i=1;i<=n;i++) { c[i]=fun(); a[c[i]]++; if(pp<c[i])pp=c[i]; } for(i=1;i<=pp;i++) { if(a[i]==0)continue; for(j=i;j<=pp;j+=i) if(a[j])b[j]+=a[i]; } printf("Case #%d: ",t); for(i=1;i<=n;i++)printf("%d%c",b[c[i]]-1,i<n?' ':'\n'); } return 0; }
G题:解题思路,代码同F题。
H题:题意不解释,水题,照着题目模拟一下就行,易错点:(1)忘记判断闰年,或者闰年判断错误,(2)输出格式容易错。
代码:
#include<stdio.h> int year, mon, day; int main(){ int T,cas=1,n,i;scanf("%d",&T); while(T--){ scanf("%d-%d-%d %d",&year,&mon,&day,&n); year+=5; printf("Case #%d: ",cas++); if(mon==2 && day == 29) { for(i = year+1; ;i++) { if(i%4==0 && i%100!=0 || i%400==0)n--; if(n == 0)break; } printf("%04d-%02d-%02d\n",i,mon,day); } else printf("%04d-%02d-%02d\n",year+n,mon,day); } return 0; }

浙公网安备 33010602011771号