Codeforces Round #319 (Div. 1) div1 A B C

来源:互联网 发布:不收费小说软件 编辑:程序博客网 时间:2024/06/06 03:32

        这把爆零居然才扣110,应该扣个200+让我刻骨铭心才对。前三题都是偏思维的,也不难,然而我恰好过了三题的pre然后全挂。

A Vasya and Petya's Game

         根据唯一分解定理,素数的整数幂必问,这样才能分辨出来。其他的数不用问,因为可以表示为素数整数幂的乘积。

#include <bits/stdc++.h>  using namespace std;  bool flag[1010];int ans[1010];bool prime[1010];int main(){    for(int i=2;i<=32;i++){        for(int j=i*2;j<=1000;j+=i){            prime[j]=1;        }    }        int n;    while(cin>>n){        int k=0;        for(int i=2;i<=n;i++){            if(prime[i])continue;            int cur=i;            if(!flag[i]){                while(cur<=n){                    ans[k++]=cur;                    flag[cur]=1;                    cur*=i;                }            }        }                cout<<k<<endl;        for(int i=0;i<k;i++){            cout<<ans[i]<<" ";        }    }    return 0;}


B Invariance of Tree

        有两种情况输出YES,第一种,有在原位置的数(循环长度为1),这种情况下拿其他所有数和它连边就行了;第二种,存在长度为2的循环,且其他所有循环的长度均为偶数,这种情况下,假设长度为2的循环是x,y,xy连一条边,对于其他的循环,循环内的数轮流连x和y。大家可以试着出奇数长度的循环和没有长度为2的循环的情况,很容易就明白了,在这样的情况下,需要大于n条边才能使得图不矛盾。

#include <bits/stdc++.h>  using namespace std;  int a[100010];bool vis[100010];int cnt[100010];int main(){    int n;    cin>>n;    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);    }        bool one=0;    bool two=0;    int root=0;    bool odd=0;    int x;    int y;    for(int i=1;i<=n;i++){        if(!vis[i]){            int cur=a[i];            while(!vis[cur]){                vis[cur]=1;                cur=a[cur];                cnt[i]++;            }            if(cnt[i]==1){                one=1;                root=i;            }            if(cnt[i]==2){            two=1;                x=i;                y=a[i];            }            if(cnt[i]>2){                if(cnt[i]&1)odd=1;            }        }    }        if(one){        cout<<"YES"<<endl;        for(int i=1;i<=n;i++){            if(i!=root){                printf("%d %d\n",root,i);            }        }    }else{        if(two&&(!odd)){            cout<<"YES"<<endl;            memset(vis,0,sizeof(vis));            printf("%d %d\n",x,y);            for(int i=2;i<=n;i++){                if(vis[i])continue;                if(i!=y&&i!=x){                    int cur=a[i];                    int q=0;                    while(!vis[cur]){                        vis[cur]=1;                        cur=a[cur];                        if(q&1){                            printf("%d %d\n",x,cur);                        }else{                            printf("%d %d\n",y,cur);                        }                        q++;                    }                }            }        }else{            cout<<"NO"<<endl;                    }    }        return 0;}


C Points on Plane

        分块。可以把横坐标分为1000份,每份长度为1000,在每个区间内,将点按纵坐标排序,轮流升序/降序输出。这样大致是一个蛇形的顺序,可以证明最坏情况下总距离不会超过限制。

#include <bits/stdc++.h>  using namespace std;  struct point{int x,y;int id;point(int x,int y):x(x),y(y){}point(){}bool operator<(const point &other)const{return x<other.x;}};point pts[1000010];vector<point> vpts[1005];int main(){int n;cin>>n;for(int i=1;i<=n;i++){scanf("%d%d",&pts[i].x,&pts[i].y);pts[i].id=i;vpts[pts[i].y/1000].push_back(pts[i]);}for(int i=0;i<=1000;i++){sort(vpts[i].begin(),vpts[i].end());}for(int i=0;i<=1000;i++){if(i&1){for(int k=0;k<vpts[i].size();k++){printf("%d ",vpts[i][k].id);}}else{for(int k=vpts[i].size()-1;k>=0;k--){printf("%d ",vpts[i][k].id);}}}return 0;}


0 0
原创粉丝点击