【CodeForces

来源:互联网 发布:牛股选股器源码 编辑:程序博客网 时间:2024/06/05 11:53

A Odds and Ends
Where do odds begin, and where do they end? Where does hope emerge, and will they ever break?

Given an integer sequence a1, a2, …, an of length n. Decide whether it is possible to divide it into an odd number of non-empty subsegments, the each of which has an odd length and begins and ends with odd numbers.

A subsegment is a contiguous slice of the whole sequence. For example, {3, 4, 5} and {1} are subsegments of sequence {1, 2, 3, 4, 5, 6}, while {1, 2, 4} and {7} are not.

Input
The first line of input contains a non-negative integer n (1 ≤ n ≤ 100) — the length of the sequence.

The second line contains n space-separated non-negative integers a1, a2, …, an (0 ≤ ai ≤ 100) — the elements of the sequence.

Output
Output “Yes” if it’s possible to fulfill the requirements, and “No” otherwise.

You can output each letter in any case (upper or lower).

Example
Input
3
1 3 5
Output
Yes
Input
5
1 0 1 5 1
Output
Yes
Input
3
4 3 1
Output
No
Input
4
3 9 9 3
Output
No
Note
In the first example, divide the sequence into 1 subsegment: {1, 3, 5} and the requirements will be met.

In the second example, divide the sequence into 3 subsegments: {1, 0, 1}, {5}, {1}.

In the third example, one of the subsegments must start with 4 which is an even number, thus the requirements cannot be met.

In the fourth example, the sequence can be divided into 2 subsegments: {3, 9, 9}, {3}, but this is not a valid solution because 2 is an even number.
题意:给定一个序列,问能否将其划分为奇数个子序列,并且每个子序列都是奇数个,并且每个子序列的头尾元素都是奇数。
分析:
乍一看 好难啊,我是想了十几分钟才想到,mmp,其实是个水题。
详细的看代码注释

#include<bits/stdc++.h>using namespace std;typedef pair<int,int>pii;#define first fi#define second se#define  LL long long#define fread() freopen("in.txt","r",stdin)#define fwrite() freopen("out.txt","w",stdout)#define CLOSE() ios_base::sync_with_stdio(false)const int MAXN = 1e5;const int MAXM = 1e6;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;int arr[MAXN];int main(){    CLOSE();//  fread();//  fwrite();    int n;scanf("%d",&n);    for(int i=1;i<=n;i++) {        scanf("%d",&arr[i]);    }    if(arr[1]%2==0||arr[n]%2==0) puts("NO"); // 这个明显不行。    else{        if(n&1) puts("YES"); //如果能够过上个if且是奇数,将其划分为1个序列就可以了。        else {//  关键就是这里,仔细想想,其实是无法构造成的。            puts("NO");         }    }    return 0;}

B
Tell Your World
Connect the countless points with lines, till we reach the faraway yonder.

There are n points on a coordinate plane, the i-th of which being (i, yi).

Determine whether it’s possible to draw two parallel and non-overlapping lines, such that every point in the set lies on exactly one of them, and each of them passes through at least one point in the set.

Input
The first line of input contains a positive integer n (3 ≤ n ≤ 1 000) — the number of points.

The second line contains n space-separated integers y1, y2, …, yn ( - 109 ≤ yi ≤ 109) — the vertical coordinates of each point.

Output
Output “Yes” (without quotes) if it’s possible to fulfill the requirements, and “No” otherwise.

You can print each letter in any case (upper or lower).

Example
Input
5
7 5 8 6 9
Output
Yes
Input
5
-1 -2 0 0 -5
Output
No
Input
5
5 4 3 2 1
Output
No
Input
5
1000000000 0 0 0 0
Output
Yes
Note
In the first example, there are five points: (1, 7), (2, 5), (3, 8), (4, 6) and (5, 9). It’s possible to draw a line that passes through points 1, 3, 5, and another one that passes through points 2, 4 and is parallel to the first one.

In the second example, while it’s possible to draw two lines that cover all points, they cannot be made parallel.

In the third example, it’s impossible to satisfy both requirements at the same time.

题意 :平面上给n个点,第i个点坐标为(i,yi)。
问能否用两条平行线(不能够重叠)穿过所有的点 。

分析一:(取巧了的思路) 后面的时间基本都是在想这个题,想了一个思路,我直接暴力一发看是什么情况吧。
我遍历所有的不重复的点对A,B,将这个点对确定的直线方程求出来,然后再遍历所有的点,用点到直线的距离。
1 > 如果都是0肯定不行,说明一条直线就穿过所有点。
2 > 如果除了距离为0的点,有一个及以上的点到直线的距离相同,那么就可以输出yes.
3 > 遍历完所有的情况,如果还没有构成就输出No.

时间复杂度应该是o(n^3)肯定是不过的,TLE了一发,然后想着TLE的最大原因就是输出NO的情况(因为要遍历所有的点),然后又想数据一定是随机的不可能卡最后几个情况,所以就随手加了个/2,800ms卡过【取巧了,TAT 还是我太菜啊~~~】

#include<bits/stdc++.h>using namespace std;typedef pair<int,int>pii;#define  LL long long#define fread() freopen("in.txt","r",stdin)#define fwrite() freopen("out.txt","w",stdout)#define CLOSE() ios_base::sync_with_stdio(false)const int MAXN = 1e5;const int MAXM = 1e6;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;vector<pii>ve;int main(){    CLOSE();//  fread();//  fwrite();    int n;scanf("%d",&n);    for(int i=1;i<=n;i++){         int a; scanf("%d",&a);         ve.push_back({i,a});    }    for(int i=0;i<ve.size()/2;i++){ // 这里减少了点范围。        for(int j=i+1;j<ve.size();j++){            int y=ve[i].second-ve[j].second; int x=ve[i].first-ve[j].first;            int cnt=2; double K=sqrt(1+(double)y*y/(double)(x*x));            //printf("x=%d  y=%d  K == %lf\n",x,y,K);            double temp=-1; int k;            for( k=0;k<ve.size();k++){                if(k==i||k==j) continue;                int yy=ve[i].second-ve[k].second; int xx=ve[i].first-ve[k].first;            //  printf("xx  %d  yy  %d\n",xx,yy);                if(xx*y==yy*x) cnt++;                else {                    double dis=(ve[k].second-ve[i].second-(double)y/x*(ve[k].first-ve[i].first))/K;                    //printf("dis== %lf \n",dis);                     if(temp==-1){                        temp=dis;                     }else {                    //  puts("===");                        if(fabs(temp-dis)>1e-6) break;                    }                }             }        //  printf("k==%d  cnt %d \n",k,cnt);            if(k!=ve.size()) continue;            if(cnt==ve.size()) continue;            puts("Yes");return 0;        }    }    puts("No");    return 0;}

分析二 看了别人的题解,才知道有一个很关键的东西,原来我上面的代码不是取巧的,就算是把上述代码 第一个循环遍历到2也是可以ac的。
关键的技巧是: 对于连续的三个点来说,其构成的三个直线,如果是能够符合题意,那么三条直线一定会有一条直线 符合题意,如果三条直线都不行,那么直接NO,这样就大大减少了 时间复杂度,这样的话,随便搞就可以了。
简化后的代码

#include<bits/stdc++.h>using namespace std;typedef pair<int,int>pii;#define first fi#define second se#define  LL long long#define fread() freopen("in.txt","r",stdin)#define fwrite() freopen("out.txt","w",stdout)#define CLOSE() ios_base::sync_with_stdio(false)const int MAXN = 1e5;const int MAXM = 1e6;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;int n;double y [MAXN];bool  solve(int a,int b){ // 以a b 两个点构成的基准直线情况     int temp=-1;    double k=(y[b]-y[a])/(double)(b-a);     for(int i=1;i<=n;i++){        if(i==a||i==b) continue;        if(fabs(y[i]-y[a]-k*(i-a))<1e-6) continue;// 以a点为基准点         if(temp==-1){ // 第一个不在基准直线             temp=i;  // 记录点         }else { // 第二个不在基准直线上             if((y[i]-y[temp])!=k*(i-temp)){ // 如果符合题意那么另一条直线的斜率一定也为k 。代码一,我用的是点到直线的距离,性质一样                 return false;              }        }    }    return temp!=-1;  // 必须至少一个点不在直线上 } int main(){    CLOSE();//  fread();//  fwrite();    cin>>n;    for(int i=1;i<=n;i++) cin>>y[i];    if(solve(1,2)||solve(1,3)||solve(2,3)) puts("Yes");    else puts("No");    return 0;}

C
C题题解链接

原创粉丝点击