Codeforces gym 2014 Nordic Collegiate Programming Contest(最初版,有过题再更新)

来源:互联网 发布:网络语言爸爸什么意思 编辑:程序博客网 时间:2024/04/26 04:15

2014.10.25 训练,和一个队友做cf上的gym的比赛,过了6题。

感觉还可以,有几道水题没有卡住,一道模拟,一道贪心,一道高精度+推公式

剩下的,一道kmp(非裸题),一道dfs搜索,一道数学期望

还有一道G题看了没做,问了学长,是一个环连着多个树,然后dp.. 没弄出来。感觉这个姿势很神奇

G I J 已经被我亮星了,改天过了,再更新本博文

已过题目:ACDEFHK

待过题目:GIJ

感觉过不了的题目(=。=!):BF



 


这题还是很简单的。

每个点要不然有登机口,要不然没有。

对于一个联通图,如果一个点确定了是否有登机口,那么这个联通图中的所有点都可以确定是否有登机口。

对于每个联通图,dfs搜索,假设起点有和没有两种情况来搜。

要分情况讨论,注意impossible成立的条件。

这里细讲太过于冗杂,就不陈述了。代码如下:

(dfs不太好写)

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN 200100#define N#define Mint n,m,a,b,c;struct Edge{    int from,to,next;    int val;}edge[2*MAXN];int head[MAXN],w;void add_edge(int from,int to,int val){    w++;    edge[w].from=from;    edge[w].to=to;    edge[w].val=val;    edge[w].next=head[from];    head[from]=w;}bool vis1[MAXN],vis2[MAXN],must[MAXN];void dfs(int now,bool *vis,int &anst){    vis[now]=true;    if(must[now]) anst+=1;    int i,to,val;    for(i=head[now];i!=-1;i=edge[i].next){        to=edge[i].to;        val=edge[i].val;        if(vis[to]){            if(must[now]&&val==0){                anst=-1;                return;            }            else if(must[now]&&val==1&&must[to]){                anst=-1;                return;            }            else if(must[now]&&val==2&&!must[to]){                anst=-1;                return;            }            else if(!must[now]&&val==0&&must[to]){                anst=-1;                return;            }            else if(!must[now]&&val==1&&!must[to]){                anst=-1;                return;            }            else if(!must[now]&&val==2){                anst=-1;                return;            }        }        else{//vis[to]=false;            if(must[now]&&val==0){                anst=-1;                return;            }            else if(must[now]&&val==1){                must[to]=false;                dfs(to,vis,anst);            }            else if(must[now]&&val==2){                must[to]=true;                dfs(to,vis,anst);            }            else if(!must[now]&&val==0){                must[to]=false;                dfs(to,vis,anst);            }            else if(!must[now]&&val==1){                must[to]=true;                dfs(to,vis,anst);            }            else if(!must[now]&&val==2){                anst=-1;                return;            }            if(anst==-1) return;        }    }}int main(){    cin>>n>>m;    repin(i,1,n){        head[i]=-1;        vis1[i]=false;        vis2[i]=false;    }    w=0;    repin(i,1,m){        scanf("%d %d %d",&a,&b,&c);        add_edge(a,b,c);        add_edge(b,a,c);    }    int ans=0,anst1,anst2;    repin(i,1,n){        if(vis1[i] || vis2[i]) continue;        must[i]=true;        anst1=0;        dfs(i,vis1,anst1);        must[i]=false;        anst2=0;        dfs(i,vis2,anst2);        if(anst1==-1&&anst2==-1){            printf("impossible\n");            exit(0);        }        else if(anst1!=-1&&anst2==-1){            ans+=anst1;        }        else if(anst1==-1&&anst2!=-1){            ans+=anst2;        }        else ans+=min(anst1,anst2);    }    printf("%d\n",ans);}







这题也不单单是高精度问题,需要将公式推出来

不难发现,Sn=C(n+1),然后求C(n)题目已经给了个公式C(n)=(2n,n)/(n+1);

(2n,n)就是排列组合中的组合问题,即2n个里选n个的总数,那么求(2n,n)复杂度就是O(n)的了

接下来就是用高精度来做,模拟下就出来了。


一开始我的思路是把每一个C(n)求出来,再求S(n),用java做T了

下面java7过的代码,c++高精度模版我还没有,以后要搞一个自己的

import java.io.*;import java.util.*;import java.math.BigInteger;public class Main {    public static void main(String[] args) throws Exception {        Scanner cin=new Scanner(System.in);        int n=cin.nextInt();        BigInteger up,down;        up=down=new BigInteger("1");        BigInteger tt=new BigInteger((2*n+2)+"");        BigInteger one=new BigInteger("1");        for(int i=1;i<=n+1;i++){            BigInteger t=new BigInteger(i+"");            down=down.multiply(t);            up=up.multiply(tt);            tt=tt.subtract(one);        }        BigInteger ans=up.divide(down);        BigInteger t1=new BigInteger((n+2)+"");        ans=ans.divide(t1);        System.out.println(ans);    }}




这题就是求期望分数

期望分数=所有的 (分数*该分数占的概率)

原谅我偷懒不写出数学公式来了0.0

最后判断浮点相等别忘了eps

代码如下:

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN 100100#define N#define M 1000int a1,b1,a2,b2,n1,n2;int number1[M],number2[M];double avepoint1,avepoint2;int dcmp(double x){    if(fabs(x)<eps) return 0;    else if(x<0) return -1;    else return 1;}int main(){    cin>>a1>>b1>>a2>>b2;    repin(i,a1,b1){        repin(j,a2,b2){            number1[i+j]+=1;        }    }    n1=(b1-a1+1)*(b2-a2+1);    avepoint1=0.0;    repin(i,a1+a2,b1+b2){        double t=(double)1.0*number1[i]/n1;        avepoint1+=t*i;    }        cin>>a1>>b1>>a2>>b2;    repin(i,a1,b1){        repin(j,a2,b2){            number2[i+j]+=1;        }    }    n2=(b1-a1+1)*(b2-a2+1);    avepoint2=0.0;    repin(i,a1+a2,b1+b2){        double t=(double)1.0*number2[i]/n2;        avepoint2+=t*i;    }    int t=dcmp(avepoint1-avepoint2);    if(t==0) printf("Tie\n");    else if(t<0) printf("Emma\n");    else printf("Gunnar\n");}



这题是贪心问题。

我不知道为什么是对的,和队友讨论了后,得出了个结论,但没有严格证明,没有图也不好说,就不陈述了。

将数列从小到大排序,从后往前扫,假设这个点左边全部用横向消除方法,右边全部用纵向消除方法

每次左边和右边的方法都可以知道需要多少步,维护最小值即可

代码如下:

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN 100100#define N#define M 1000int n,ans;int h[MAXN];int main(){    cin>>n;    repin(i,1,n){        scanf("%d",h+i);    }    sort(h+1,h+1+n);    ans=n;    depin(i,n,1){        int t=h[i]+(n-i);        ans=min(ans,t);    }    cout<<ans<<endl;}




给两个时钟,每个时钟有n个指针,方向散乱无序,告诉你12点钟方向顺时针转到该指针的角度是多少

问,将第一个时钟旋转某个角度,是否可以和第二个时钟完全重合?

只需要输出是否即可,不需要知道旋转多少度


思路如下

将2个时钟指针角度都从小到大排序

每个时钟求出下一个指针和上一个指针的角度差,构成2个数组(注意这个过程末尾和第一个指针构成的角度)

现在需要做的是,判断下一个数组头尾移动后,能否和第一个数组重合。


将第一个数组复制一遍,从n长度,变成2n,d1[i+n]==d[i]

那么,问题就变成了,下面这个长度为n的数组,是否是上面那个长度为2n数组的子串

跑一发kmp就出来了


代码如下:

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN 200100#define N#define Mint n;int a[MAXN],b[MAXN];int d1[2*MAXN],d2[MAXN];int nextpos[MAXN];void Build_nextpos(){    int i,j;    i=0;    nextpos[0]=j=-1;    while(i<n){        if(j==-1 || d2[i]==d2[j]){            nextpos[i+1]=j+1;            if(d2[j+1]==d2[i+1]) nextpos[i+1]=nextpos[j+1];            i++;            j=j+1;        }        else j=nextpos[j];    }}bool kmp(){    int i,j;    i=j=0;    while(i<2*n && j<n){        if(j==-1 || d1[i]==d2[j]){            i++;            j++;        }        else j=nextpos[j];    }    if(j==n) return true;    else return false;}int main(){    cin>>n;    rep(i,0,n){        scanf("%d",a+i);    }    sort(a,a+n);    rep(i,0,n){        scanf("%d",b+i);    }    sort(b,b+n);    rep(i,0,n){        if(i==n-1) d1[i]=360000-a[i]+a[0];        else d1[i]=a[i+1]-a[i];    }    rep(i,n,2*n){        d1[i]=d1[i-n];    }    rep(i,0,n){        if(i==n-1) d2[i]=360000-b[i]+b[0];        else d2[i]=b[i+1]-b[i];    }    Build_nextpos();    if(kmp()) printf("possible\n");    else printf("impossible\n");}




简单模拟题

判断火车人数是否小于0

判断火车人数是否超过限制

判断火车是否存在人没满但却有人等待的情况

判断最终火车是否为空

代码如下:

//Hello. I'm Peter.#include<cstdio>#include<iostream>#include<sstream>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<algorithm>#include<functional>#include<cctype>#include<ctime>#include<stack>#include<queue>#include<vector>#include<set>#include<map>using namespace std;typedef long long ll;typedef long double ld;#define peter cout<<"i am peter"<<endl#define input freopen("data.txt","r",stdin)#define randin srand((unsigned int)time(NULL))#define INT (0x3f3f3f3f)*2#define LL (0x3f3f3f3f3f3f3f3f)*2#define gsize(a) (int)a.size()#define len(a) (int)strlen(a)#define slen(s) (int)s.length()#define pb(a) push_back(a)#define clr(a) memset(a,0,sizeof(a))#define clr_minus1(a) memset(a,-1,sizeof(a))#define clr_INT(a) memset(a,INT,sizeof(a))#define clr_true(a) memset(a,true,sizeof(a))#define clr_false(a) memset(a,false,sizeof(a))#define clr_queue(q) while(!q.empty()) q.pop()#define clr_stack(s) while(!s.empty()) s.pop()#define rep(i, a, b) for (int i = a; i < b; i++)#define dep(i, a, b) for (int i = a; i > b; i--)#define repin(i, a, b) for (int i = a; i <= b; i++)#define depin(i, a, b) for (int i = a; i >= b; i--)#define pi acos(-1.0)#define eps 1e-6#define MOD 1000000007#define MAXN 100100#define N#define M 1000int c,n,nowcapacity;void impossible(){    printf("impossible\n");    exit(0);}int main(){    cin>>c>>n;    nowcapacity=0;    int out,in,wait;    repin(i,1,n){        scanf("%d %d %d",&out,&in,&wait);        nowcapacity-=out;        if(nowcapacity<0) impossible();        nowcapacity+=in;        if(nowcapacity>c) impossible();        if(nowcapacity!=c && wait!=0) impossible();    }    if(nowcapacity!=0) impossible();    printf("possible\n");}



0 0
原创粉丝点击