2017-10-30离线赛总结

来源:互联网 发布:e4a 下载网络图片 编辑:程序博客网 时间:2024/06/05 15:41

失分小结:
估分:150
实际分数:170
最后半个小时发现自己第一题敲错了,心态爆炸,拿暴力对拍,拍一组错一组
直到最后还没调出来,就只好把暴力丢上去,胡了50分
后面两题不敢想正解,就随便每题切了60分(后来发现机房的神犇门都想出了正解,泪奔
两天一共375分 感觉两天都只敲了暴力 比省一线高了45分 如果是现场比赛估计也不会有这个分

收获:
对拍一定要是最暴力的!!!

题解:
第一题:
由除法的性质可知:由于组合数是可以递推的,只要在递推的过程中不断地取模,就能判断组合数是否能被k整除,且值不会超过int,然后就是前缀和维护,O(1)查询

#include<bits/stdc++.h>using namespace std;int ans[2005][2005];int C[2005][2005];int main(){    int T,k;    scanf("%d%d",&T,&k);    memset(C,-1,sizeof(C));    for(int i=1;i<=2000;i++){        C[i][i]=C[i][0]=1;        for(int j=1;j<i;j++){            C[i][j]=C[i-1][j-1]+C[i-1][j];            C[i][j]%=k;        }    }    for(int i=1;i<=2000;i++){        for(int j=1;j<=2000;j++){            ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];            if(!C[i][j])ans[i][j]++;        }    }    while(T--){        int n,m;        scanf("%d%d",&n,&m);        printf("%d\n",ans[n][min(n,m)]);    }    return 0;}

第二题
类似于曾经的一道瑞士轮,在本无序的序列中快速找到最大值
这里利用原序列,拆开后的大小序列组成的三个序列构成三个递减序列
然后用队列维护就好了 切分乱我心智

#include<bits/stdc++.h>using namespace std;#define ll long longint n,m,Q,u,v,t;int A[100005];long long ans[7000005];template<class T>struct Queue{    T a[10000000];    int l=1,r=0;    bool empty(){return l>r;}    void push(T x){a[++r]=x;}    T front(){return a[l];}    void pop(){l++;}};Queue<long long>q[3];long long a[3];int main(){    scanf("%d%d%d%d%d%d",&n,&m,&Q,&u,&v,&t);    for(int i=1;i<=n;i++)        scanf("%d",&A[i]);    sort(A+1,A+n+1);    for(int i=n;i>=1;i--)        q[0].push(A[i]);    for(int k=1;k<=m;k++){        ans[k]=-1e9;        for(int i=0;i<=2;i++){            a[i]=-1e9;            if(!q[i].empty())a[i]=q[i].front();            if(ans[k]<a[i])ans[k]=a[i];        }        for(int i=0;i<=2;i++){            if(a[i]==ans[k]){                q[i].pop();                a[i]+=Q*(k-1);                long long l1=1ll*a[i]*u/v;                long long l2=a[i]-l1;                if(l1>l2)swap(l1,l2);                q[1].push(l1-Q*k),q[2].push(l2-Q*k);                break;            }        }        ans[k]+=Q*(k-1);    }    for(int i=1;i<=m;i++)        if(i%t==0)printf("%lld ",ans[i]);    puts("");    for(int i=1;i<=n+m;i++){        int mx=-1e9,id=-1;        for(int k=0;k<=2;k++){            if(q[k].empty())continue;            if(q[k].front()>mx){                mx=q[k].front();                id=k;            }        }           q[id].pop();        if(i%t==0)printf("%d ",mx+m*Q);    }    puts("");    return 0;}

第三题:
看到n=20内心毫无波澜又可以爆搜多水一些分了
裸裸的状压啊!!!
预处理:
任取两点作为函数的两点确定a,b
然后看这个函数能穿过多少个点,
主函数就是单纯的状压:

#include<bits/stdc++.h>using namespace std;const int M=21;#define du double#define EPS 1e-6struct node{du x,y;}A[M];int Sum[M*M],dp[1<<M],n,m,cnt,T;template <class _> _ Abs(_ x){return x>=0?x:-x;}template <class _> void chk_mi(_ &x,_ y){if(x==-1||x>y)x=y;}bool check(node a,node b,du &fi,du &se){    du k1=a.x*a.x,k2=a.x,k3=a.y;    du k4=b.x*b.x,k5=b.x,k6=b.y;    du x=(k3*k5-k2*k6);    du y=(k5*k1-k2*k4);    if(y==0)return 0;    fi=x/y;    if(fi>=0)return 0;    se=(k3-k1*fi)/k2;    return 1;}bool True(node T,du a,du b){    du d=Abs(T.x*T.x*a+T.x*b-T.y);    return d<=EPS;}void init(){    for(int i=1;i<=n;i++){        for(int j=i+1;j<=n;j++){            du a,b;            if(!check(A[i],A[j],a,b))continue;            Sum[++cnt]|=1<<(i-1);            Sum[cnt]|=1<<(j-1);            for(int k=j+1;k<=n;k++){                if(k==i||k==j)continue;                if(!True(A[k],a,b))continue;                Sum[cnt]|=1<<(k-1);            }        }    }}int main(){    scanf("%d",&T);    for(int cas=1;cas<=T;cas++){        memset(dp,-1,sizeof(dp));        memset(Sum,0,sizeof(Sum));        cnt=0;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)scanf("%lf%lf",&A[i].x,&A[i].y);        init();        int tta=(1<<n)-1;        dp[0]=0;        for(int i=0;i<=tta;i++){            if(dp[i]==-1)continue;            for(int k=1;k<=cnt;k++)                chk_mi(dp[i|Sum[k]],dp[i]+1);            for(int k=0;k<n;k++)                if((i&(1<<k))==0)                    chk_mi(dp[i|(1<<k)],dp[i]+1);        }        printf("%d\n",dp[tta]);    }    return 0;}
原创粉丝点击