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;
}

 

posted @ 2013-11-09 19:25  线性无关  阅读(328)  评论(1)    收藏  举报