2014届第一场排位赛

1275 :母亲节快乐!
题目链接: http://oj.jxust.cn/problem.php?id=1275
这道题的通过率这么低是我始料未及的呀!
这道题目其实应该来说是一道数学题,但是要比数学题更加严谨,要求n个点是都在同一条直线上有恒多种做法这里简单的介绍两种方法:
1) 求相邻的两个点的斜率判断他们是否相等,注意要将坐标转化为浮点型(如果数据量再大点就要做精度的处理),特别要注意斜率不存在的情况,如果斜率不存在的话,就会除以0,就会产生运行错误。

2) 可以将三个点作为一组p1(x1,y1),p2(x2,y2),p3(x3,y3),判断Kp1p2是否等于Kp2p3只需要判断(y2-y1)*(x2-x1)是否等于(y3-y2)*(x2-x1),此时就不用判断斜率了,但是要注意两个点的时候要特判!(上述等式是两个斜率对角相乘)

//用三个点的方法判断
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 1000005
int x[N],y[N];
int main()
{
    int n,m,flag;
    while(~scanf("%d",&n))
    {
        flag = 0;
        for(int i=0; i<n; i++)
            scanf("%d%d",&x[i],&y[i]);
        if(n>2)
        {
            for(int i=2; i<n; i++)
            {
                if((y[i]-y[i-1])*(x[i-1]-x[i-2])!=(x[i]-x[i-1])*(y[i-1]-y[i-2]))
                {
                    flag =1;
                    break;
                }
            }
        }
        if(!flag||n==2)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}
//两个点判断
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int n;
    double x, y, a, b, ans;
  
    while(~scanf("%d", &n))
    {
        scanf("%lf%lf", &x,&y);
        scanf("%lf%lf", &a,&b);
        int flag = 0;
        if(a == x) flag = 1;
        else ans = fabs(b-y)/fabs(a-x);
        for(int i=3; i<=n; i++)
        {
            scanf("%lf%lf", &a,&b);
            if(flag == 1)
            {
                if(a != x) flag = 2;
            }
            else if(fabs((b-y)/(a-x) - (ans)) > 1e-5) flag = 2;
        }
        if(flag > 1) puts("NO");
        else puts("YES");
    }
    return 0;
}



1276:洋洋要比赛

题目链接:http://oj.jxust.cn/problem.php?id=1276
greedy:
要使花费时间最短,就应该使做题的顺序中有更多的后面的题目长度和难度系数大于等于前面的长度和难度系数的片段, 所以可以先按照长度由小到大排序,如果长度相等则按难度系数从小到大排序。然后再按顺序找出长度和难度系数也比前面一个大或等于的题目,看最多有多少个连续的片段, n-连续片段的数量就是answer. 复杂度为O(n*n).

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 5005
int vis[N];
struct node
{
    int time;
    int level;
};
 
int cmp(node a,node b)
{
    if(a.time==b.time)
        return a.level<b.level;
    else
        return a.time<b.time;
}
 
node ans[N];
int main()
{
    int T,n,sum,res;
    cin>>T;
    while(T--)
    {
        sum = 0;
        cin>>n;
        memset(vis,0,sizeof(vis));
        for(int i=0; i<n; i++)
            cin>>ans[i].time>>ans[i].level;
        sort(ans,ans+n,cmp);
        for(int i=0; i<n; i++)
        {
            if(!vis[i])
            {
                res = i;
                //cout<<ans[i].level;
                for(int j=i+1; j<n; j++)
                {
                    if(ans[res].level<=ans[j].level&&!vis[j])
                    {
                        vis[j] = 1;
                        res = j;
                       // cout<<" "<<ans[j].level;
                    }
 
                }
                //cout<<endl;
                sum++;
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}



1277:吃货问生日

http://oj.jxust.cn/problem.php?cid=1046&pid=2

其实就是一道升级版的判断闰年

//普通版
//by:qwn3213
//从开始年到结束年,遍历一遍,判断每一年是否是闰年,时间复杂度为O(n)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

bool isLeap(int y)
{
    if(y%400==0||y%4==0&&y%100!=0)
        return true;
    else return false;
}

int main()
{
    char month[][20]= {"sb","January","February","March","April","May","June","July","August","September","October","November" ,"December"};
    int t,j,i,year1,year2,day1,day2,month1,month2,ans;
    char m1[20],m2[20];

    cin>>t;
    for(i=1; i<=t; i++)
    {
        ans=0;
        scanf("%s %d,%d",&m1,&day1,&year1);
        scanf("%s %d,%d",&m2,&day2,&year2);

        for(j=1; j<13; j++)
            if(strcmp(m1,month[j])==0)
            {
                month1=j;
                break;
            }
        for(j=1; j<13; j++)
            if(strcmp(m2,month[j])==0)
            {
                month2=j;
                break;
            }
            
        if(year1==year2)
        {
            if(isLeap(year1))
                if((month1<3&&month2>2)||(month2==2&&day2==29))
                    ans=1;
        }
        else
        {
            for(j=year1+1;j<year2;j++)
                if(isLeap(j))
                    ans++;
            if(isLeap(year1))
                if(month1<3)
                    ans++;
            if(isLeap(year2))
                if(month2>2||(month2==2&&day2==29))
                    ans++; 
        }
        
        printf("Case #%d: %d\n",i,ans);
    }
    return 0;
}


//高级版
//by:qwn3213
//时间复杂度为O(1),这道题其实一开始我year的范围是设定到10亿的,这样O(n)方法就超时了
//后来降低难度了,没想到还是只有两个人AC了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
    int t,j,i,year1,year2,day1,day2,ans,monthth1,month2;
    char m1[20],m2[20];
    int a,b;
    cin>>t;
    for(i=1; i<=t; i++)
    {
        ans=0;
        scanf("%s %d,%d",&m1,&day1,&year1);
        scanf("%s %d,%d",&m2,&day2,&year2);
 
        if(strcmp(m1,"January")==0||(strcmp(m1,"February")==0&&day1<=29))
            year1--;
        if(strcmp(m2,"January")==0||(strcmp(m2,"February")==0&&day2<29))
            year2--;
         
        a=year2/4-year2/100+year2/400;   //a:year2是第几个闰年
        b=year1/4-year1/100+year1/400;
        ans+=a-b;
          
        printf("Case #%d: %d\n",i,ans);
    }
    return 0;
}




1278:Operate Sequence
http://oj.jxust.cn/problem.php?id=1278
只是想写个英文标题吓吓大家,结果比赛的时候真没人做。。
其实这题很简单:要把最后一个元素一个一个放到最前面去使得其变成一个非递减序列就必须满足两个条件:①原先的序列原本就是非递减的,或者它有两段非递减序列(想想看是不是)。②原先序列的最后一个元素要比第一个元素小或相等(要不然放到前面去也不会是非递减的)。满足这两个限制条件就可以操作成非递减序列了,求最小操作数就是找出原先序列中最先不符合非递减序列的数的位置,你说把那个数放到序列中第一个位置最少需要几步?如果原本就是非递减的答案就是0.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 100005
int res[N];
int main()
{
   int T,n,ans,i,j,k,flag;
   cin>>T;
   while(T--)
   {
       flag = 0;
       scanf("%d",&n);
       for(i=0; i<n; i++)
        scanf("%d",&res[i]);
       for(i=1; i<n; i++)
        if(res[i]<res[i-1])
           break;
       for(j=i+1;j<n;j++)
       {
           if(res[j]<res[j-1])
           {
               flag = 1;
               break;
           }
       }
       if((!flag&&res[n-1]<=res[0])||(!flag&&i==n))
       cout<<n-i<<endl;
       else
        cout<<-1<<endl;
 
   }
   return 0;
}
 



1279:出题,一开始我是拒绝的

题目链接:http://oj.jxust.cn/problem.php?cid=1046&pid=4

数组A、B数据量都是10000,所以这道题不能开数组存C,再排序,再遍历

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
//by:qwn3213
int main()
{  
    int a[10240],b[10240],n,m,k,i,j,ans;
    while(cin>>n>>m>>k)
    {
        ans=1;
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(j=0;j<m;j++)
            scanf("%d",&b[j]);
        sort(a,a+n);
        sort(b,b+m);
        j=m-1;
        for(i=0;i<n;i++)
        {
            for(;j>=0&&a[i]+b[j]>=k;j--);
            //因为a、b都有序的所以j每次不需要从头到尾遍历,
            //可以从上次的结果开始,减少很多很多时间
            //其实这也可以用二分做,自己想去吧
            ans+=j+1;
        }
        cout<<ans<<endl;
    }  
}



1281:加油吧,兄弟!
http://oj.jxust.cn/problem.php?id=1281
这道题有点贪心的感觉,找到一种最优解。这道题目还是挺有趣的,很多人赛后问我说这道题我尽量将1,11,111……加入其中怎么就错了,然后我给了他一个20的数据,他就回了句。。。。,这道题的要求是输出个数最少的完美数,咋一看还是挺难的,仔细一看也还是不简单哈,其实解法很简单,就是要自己仔细分析,找出他们之间的一种规律(这就要靠大家自己平时做题的积累了)。这题只需要先判断几位数然后将每一位数字跟1比较,若大于等于1,则赋1,否则赋0.
例如: 2054 先将2跟1比较,2>1,故第一位赋1,第二位0,0<1,故第二位赋0,第三位5>1,故第三位赋1,第四位4,4>1,故赋1.
所以第一个数就是:1011,剩下2054 - 1011 = 1043,然后按照这种方式继续下去。

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
    int a[100];
    int T,n,flag,i,j,k,t,ans[100],res[100],temp,MAX,sum;
    cin>>T;
    while(T--)
    {
        cin>>n;
        k=0;
        temp = n;
        while(temp)
        {
            ans[k] = temp%10;
            a[k++]=temp%10;
            temp = temp/10;
        }
        sort(a,a+k);
        MAX = a[k-1];
        cout<<MAX<<endl;
        for(i=0;i<MAX;i++)
        {
            flag = 0,sum=0,t=0;
            for(j=0;j<k;j++)
            {
                if(ans[j]>=1)
                {
                    res[flag++] = 1;
                    ans[j]--;
                }
                else
                    res[flag++] = 0;
            }
            for(j=0;j<flag;j++)
            sum+=(res[j]*pow(10.0,t++));
            if(i==0)
            cout<<sum;
            else
                cout<<" "<<sum;
        }
        cout<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值