zoukankan      html  css  js  c++  java
  • 20170910模拟赛

    啊啊啊lrb巨神出题不按难度排序坑死人啦!!!

    忠告:正向做题,否则AK!

    rk11,总体还是有一定进步,但是我可以300的!!!!!!

    不说了,都是泪~

    T1:(大丧题)

    CCT

    最近学校又发了n本五三题霸,BBS看到后十分高兴。但是,当他把五三拿到手后才发现,他已经刷过这些书了!他又认真地看了一会儿,发现新发的这些五三是2017版的,而他刷的是2016版的。现在他想找出所有他没有刷过的题来刷。每本五三都有m道题,并且它的特征(即它和去年版本的五三的差距)可以用一个m位二进制数来代表,二进制位上的1代表该题不同,0代表该题相同。比如4(100)就代表题目3和去年的有不同、5(101)就代表题目1和题目3和去年的有不同。而BBS热衷于给自己找麻烦,他要选择连续一段的几本五三一起刷,并且要求,所有选择的五三的特征中的所有k位中每一位出现1的次数都相同。他又想去刷最多的书,请你告诉他,他最多能刷多少本书?

    输入格式:

    第一行为两个整数 n、m,接下来的n行为 n 个整数,表示每本五三的特征。

    输出格式:

    一个整数,表示BBS最多能刷几本书。

    样例输入

    样例输出

    7 3

    7

    6

    7

    2

    1

    4

    2

    4

    样例解释:

    这7本五三的特征分别为111,110,111,010,001,100,010。选择第3本至第6本五三,这些五三的特征中每一位都出现了2次1。当然,选择第4本到第6本也是可以的,这些五三的特征中每一位都出现了1次1。只是这样子BBS刷的书的数量就少了,他就会不高兴。

    数据范围:

    对于 100%的数据:1<=n<=100000,1<=k<=30。 

    原题:[usaco2007 March Gold]Balanced Lineup

    题解:

    首先可以知道,对于一个特征值a1a2a3..am,可以用(a1-a1)(a2-a1)(a3-a1)...(am-a1)表示它,再做一遍前缀和,得到(s1-s1)(s2-s1)(s3-s1)...(sm-s1)。容易证明,对于两个相同的状态,他们经过处理后的前缀和是一样的。

    可以设t1=s1s2...sm,t2=(s1+x)(s2+x)...(sm+x),则两数之间的差为xx...x,满足条件

    处理后,t1=(s1-s1)(s2-s1)...(sm-s1),t2=(s1+x-s1-x)(s2+x-s1-x)...(sm+x-s1-x)=(s1-s1)(s2-s1)...(sm-s1),即t1=t2。

    所以当两个前缀和pre[i],pre[j]相同的时候,可以推出[i,j-1]或[i+1,j]是合法的区间。

    所以可以直接开一个set记录一种前缀和第一次出现的位置,边遍历边更新即可。

    代码:

    #include<cstdio>
    #include<set>
    #define max(a,b) (a>b?a:b)
    using std::set;
    int n,m,ans;
    struct AriM{
        int x;
        int dig[32];
        friend bool operator<(AriM a,AriM b){
            for(int i=1;i<m;i++)
                if(a.dig[i]!=b.dig[i])return a.dig[i]<b.dig[i];
            return 0;
        }
    }t;
    set<AriM>s;
    int pre[100005][32];
    inline int read(){
        int x=0,f=1;char c=getchar();
        for(;c<'0'||c>'9';f=c=='-'?-1:1,c=getchar());
        for(;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0',c=getchar());
        return x*f;
    }
    int main(){
        freopen("cct.in","r",stdin);
        freopen("cct.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=n;i++)
            for(int j=1,x=read();j<=m;j++)
                pre[i][j]=pre[i-1][j]+x&(1<<(j-1));
        s.insert(t);
        for(int i=1;i<=n;i++){
            t.x=i;
            for(int j=1;j<m;j++)t.dig[j]=pre[i][j]-pre[i][j+1];
            set<AriM>::iterator it=s.find(t);
            if(it==s.end())s.insert(t);
            else ans=max(ans,i-(*it).x);
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    T2:

    MHM

           LGL今天一共要上n节课,这n节课由0标号至n。由于过度劳累,除了第0节课和第n节课,LGL还打算睡上m节课,所以他做了一个睡觉计划表。通过小道消息,LGL得知WQ今天会在学校中检查,所以他想少睡k节课。但是由于某些原因,他又想使相邻的两节睡觉的课之间上的课数量的最小值最大。由于他很困,所以他请你来帮他计算这个值。

     

    输入格式:

    第一行为三个整数 n、m、k,接下来的m行为m个整数ai,表示睡觉计划表中LGL想要睡觉的课。

    输出格式:

    一个整数,表示题目所求的值。

    样例输入

    样例输出

    25 5 2

    14

    11

    17

    2

    21

    3

    样例解释:

    选择第2节和第14节不睡觉,这样子相邻的两节睡觉的课之间上的课数量的最小值为3,即第17节和第21节之间和第21节到第25节之间。没有答案更大的删除方案。

    数据范围:

    对于100%的数据:1<=n<=109,1<=k<=m<=50000,0<ai<n。

    原题:noip2015提高组d2t1

    题解:傻逼二分,check,输出答案(这么水的题我居然打炸了)

    细节见代码:

    #include<cstdio>
    #include<algorithm>
    #define mid (l+r>>1)
    int n,m,k,l,r,a[50005];
    inline int read(){
        int x=0,f=1;char c=getchar();
        for(;c<'0'||c>'9';f=c=='-'?-1:1,c=getchar());
        for(;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0',c=getchar());
        return x*f;
    }
    bool check(int x){
        for(int i=1,pos=0,cnt=0;i<=m;i++)
            if(a[i]-pos<=x){if(++cnt>k)return 0;}
            else pos=a[i];
        return 1;
    }
    int main(){
        freopen("mhm.in","r",stdin);
        freopen("mhm.out","w",stdout);
        n=r=read();m=read();k=read();
        for(int i=1;i<=m;i++)a[i]=read();
        std::sort(a+1,a+m+1);a[++m]=n;
        while(l<=r)check(mid)?l=mid+1:r=mid-1;
        printf("%d
    ",l-1);
        return 0;
    }
    View Code

    T3:

    AAFA

     YYH有n道题要做。每一道题都有一个截止日期t,只要在该日期之前做完,他的父亲LRB就会奖励他w元钱。令人惊讶的是,每一道题他都只需要1秒来做。请问他最多能从父亲那里拿到多少钱?

    输入格式:

    第一行为一个整数 n,接下来的n行每一行都有两个数ti和wi,分别表示第i题的截止日期和奖励。

    输出格式:

    一个整数,表示YYH的最大获利。

    样例输入

    样例输出

    3

    2 10

    1 5

    1 7

    17

    样例解释:

                         第1秒做第3道题,第2秒做第1道题。

    数据范围:

    对于 100%的数据:1<=n、ti 、wi <=100000。

    (原创题)

    题解:

    首先可以按照截止时间把作业排序,然后从前往后扫描。

    当选到第i个的时候,若已选数量小于截止时间,则选该任务一定比不选要优。

    若已选数量等于截止时间,则考虑能否用该任务替代以前所选的最小收益任务,可以直接把已选任务丢进一个小根堆,直接与堆顶元素比较即可。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using std::priority_queue;
    typedef long long ll;
    struct AriM{
        int t,w;
        friend bool operator<(AriM a,AriM b){
            return a.t<b.t;
        }
    }a[100005];
    priority_queue<int,std::vector<int>,std::greater<int> >q;
    int n;
    ll ans,sz;
    template<typename T>T read(){
        T x=0,f=1;char c=getchar();
        for(;c<'0'||c>'9';f=c=='-'?-1:1,c=getchar());
        for(;c>='0'&&c<='9';x=x*10+c-48,c=getchar());
        return x*f;
    }
    int main(){
        freopen("aafa.in","r",stdin);
        freopen("aafa.out","w",stdout);
        n=read<int>();
        for(int i=1;i<=n;i++)a[i].t=read<ll>(),a[i].w=read<ll>();
        std::sort(a+1,a+1+n);
        for(int i=1;i<=n;i++,sz=q.size())
            if(sz<a[i].t)q.push(a[i].w);
            else if(sz==a[i].t&&q.top()<a[i].w)
                q.pop(),q.push(a[i].w);
        while(!q.empty())ans+=q.top(),q.pop();
        printf("%I64d
    ",ans);
        return 0;
    }
    View Code

    T4:

    ZZI

           YYH拿到了父亲给的钱欣喜若狂,把这些钱拿来造了n栋房子。现在他要给这些房子通电。他有两种方法:第一种是在房间里搭核电发电机发电,对于不同的房子,他需要花不同的代价Vi;,第二种是将有电的房子i的电通过电线通到没电的房子j中,这样子他需要花的代价为aij。他现在请你帮他算出他最少要花多少钱才能让所有的房子通上电。

    输入格式:

    第一行为一个整数 n。接下来的n行为 n 个整数vi,再接下来的n行每行n个数,第i行第j列的数表示aij

    输出格式:

    一个整数,表示最小代价。

    样例输入

    样例输出

    4
    5

    4

    4

    3
    0 2 2 2
    2 0 3 3
    2 3 0 4
    2 3 4 0

    9

    样例解释:

    在第4栋房子造核电发电机,再将其他三栋房子通过电线连向它。

    数据范围:

    对于 100%的数据:1<=n<=300,1<=vi,aij<=100000,保证aii=0,aij=aji

    经典的供电问题,但我没打过233

    题解:

    仔细读题,可以证明最优方案一定由x个发电机和(n-x)条电线组成,符合MST的性质。

    于是考虑新增加一个0号节点,与1~n号节点连权值为vi的双向边,节点i和节点j之间连权值为aij的双向边,直接跑一遍prim即可。

    代码:

    #include<cstdio>
    #define inf 0x3f3f3f3f
    #define min(a,b) (a<b?a:b)
    int n;
    int d[305],map[305][305];
    bool used[305];
    inline int read(){
        int x=0,f=1;char c=getchar();
        for(;c<'0'||c>'9';f=c=='-'?-1:1,c=getchar());
        for(;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0',c=getchar());
        return x*f;
    }
    int prim(){
        int res=0;
        for(;;){
            int pos=-1,lim=inf;
            for(int i=1;i<=n;i++)
                if(!used[i]&&d[i]<lim)
                    lim=d[i],pos=i;
            if(pos<0)return res;
            res+=d[pos];used[pos]=1;d[pos]=0;
            for(int i=1;i<=n;i++)
                if(!used[i])d[i]=min(d[i],map[pos][i]);
        }
    }
    int main(){
        freopen("zzi.in","r",stdin);
        freopen("zzi.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)d[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                map[i][j]=read();
        printf("%d
    ",prim());
        return 0;
    }
    View Code
  • 相关阅读:
    Sass代码重用----Sass继承
    Sass代码重用
    Scss基本运算-------颜色运算
    Scss基本运算-------字符运算
    Scss基本运算-------数字运算
    7.Scss的基本运算
    6.Scss注释
    css横竖屏判断
    禁止页面缩放及meta便签常用属性
    微信小程序 错误记录
  • 原文地址:https://www.cnblogs.com/Marser/p/7502743.html
Copyright © 2011-2022 走看看