• 20171018 校内模拟赛 题解


    T1.小 Z 切课本(cut)
    小 Z 厌恶数学,他决定将数学课本切成一块一块的。他的课本是一个 n*m 的
    矩形,小 Z 决定切 K 刀,每刀他可以横着切或者竖着切,但是切成的矩形的长和
    宽都必须是整数。当然,小 Z 不会做出两次相同的操作。
    不巧的是,小 Z 的数学老师知道了他这个行为,并且刁钻的老师肯定会找到
    切出的矩形中面积最小的那一块来 D 他, 所以小 Z 想知道最优情况下面积最小
    的那一块面积最大能是多少?
    [输入格式]
    从 cut.in 中读取数据。
    输入数据只包含一行三个整数 n,m,k,含义如题目所述。
    [输出格式]
    输出一个数字,表示答案。 如果没有合法的方案,输出-1。
    [样例输入]
    6 4 2
    [样例输出]
    8

    [数据范围与约定]

    本题采用子任务制,你只有通过一个 subtask 下的所有测试点才能得到对应的分
    数。
    Subtask1 : 包含 20Points 满足 n,m<=10
    Subtask2 : 包含 20Points 满足 n,m<=5000
    Subtask3 : 包含 20Points 满足 n,m<=10^7
    Subtask4 : 包含 40Points 满足 n,m<=10^9
    对于所有数据,满足 n,m,k>=1, k<=10^9

    题解

    如果能只切一边的话,只切一边一定最优。
    假设 n<=m, k>=m 时,考虑将一边全部切开,剩下的平均切到另一边。 长的边切 m-1 刀,
    另一边切 k-(m-1)刀一定最优因为, n/(k-(n-1))>=m/(k-(m-1))。

    #include<cstdio>
    long long n,m,k;
    int main(){
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        scanf("%lld%lld%lld",&n,&m,&k);
        if(n+m-2<k){
            puts("-1");return 0;
        }
        if(n>m){
            long long t=n;n=m;m=t;
        }
        if(m>=k+1){
            if(n/(k+1)*m>m/(k+1)*n) printf("%lld",n/(k+1)*m);
            else printf("%lld",m/(k+1)*n);
        }
        else{
            if(m/(k-(n-1)+1)>n/(k-(m-1)+1)) printf("%lld",m/(k-(n-1)+1));
            else printf("%lld",n/(k-(m-1)+1));
        }
        return 0;
    }

    T2.小 Z 爱数组(array)
    小 Z 最喜欢数组了,现在他得到了由 n 个正整数组成的数组 ai,他想构造
    一个相同大小的正整数数组 bi 满足两个数组的差异度 |ai - bi|最小。特殊的

    是, bi 数组的所有元素必须满足两两互质。

    题解

    原题 ai 不超过 30,所以选择的 bi 肯定小于 59,不然可以用 1 代替。
    58 以内只有 16 个质数,所以将这些质数的状态压起来之后 dp 即可,复杂度 O(2^16*n*58)
    T3.小 Z 爱修路
    把所有新加的边去个重,到相同的点的边只保留一个最小的,然后跑一次最短路。一条新加
    的边如果长度不是最短路一定可以去掉,否则只有满足有其它最短路径到达这个点的时候才
    可以去掉。算出到每个点最短路条数是否大等于 2 即可。
    复杂度 O((n+k)logn)

    还没打,先贴标程。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define MN 100
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int p[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
    int f[MN+5][1<<16],from[MN+5][1<<16],n,a[MN+5],bit[MN+5],q[MN+5];
    void R(int&x,int&y,int X,int Y){X<x?(x=X,y=Y):0;}
    inline int abs(int x){return x<0?-x:x;}
    int main()
    {
        freopen("array.in","r",stdin);
        freopen("array.out","w",stdout);
        n=read();
        for(int i=1;i<=n;++i) a[i]=read();
        memset(f,63,sizeof(f));f[0][0]=0;
        for(int i=1;i<59;++i)
            for(int j=0;j<16;++j) if(i%p[j]==0) bit[i]|=1<<j;
        for(int i=1;i<=n;++i) for(int j=0;j<1<<16;++j) if(f[i-1][j]<1e9)
            for(int k=1;k<59;++k) if(!(bit[k]&j)) R(f[i][j|bit[k]],from[i][j|bit[k]],f[i-1][j]+abs(k-a[i]),k);
        int mn=1e9,fr=0;
        for(int i=0;i<1<<16;++i) if(f[n][i]<mn) mn=f[n][i],fr=i;
        for(int i=n,j=fr;i;j^=bit[from[i--][j]]) q[i]=from[i][j];
        for(int i=1;i<=n;++i) printf("%d ",q[i]);
        return 0;    
    }

    T3.小 Z 爱修路(road)
    L 国包含 n 个城市和 m 条双向道路,第 i 条道路连接 ui,vi 两个城市, 距离为
    ti,这些道路将所有 n 个城市连接在一起。 明年, L 国将会在首都,也就是 1 号
    城市举办一年一度的 noi,所以 L 国的国王委托小 Z 新建一些道路来减少一些城
    市到达首都的距离。小 Z 很快修好了道路,但是他却不是很满意。他想知道最多
    可以少新建多少道路,满足首都到所有城市的最短路长度和现在相同。
    [输入格式]
    从 road.in 中读取数据。
    第一行读入三个数字 n,m,k,依次表示城市的数量,原有道路的数量和新建道路
    的数量。
    接下来 m 行,每行三个数字 ui,vi,ti,表示一条原有的道路
    最后 k 行,每行两个数字 si,wi,表示一条新建的道路连接 1 和 si,距离为 wi。
    [输出格式]
    输出一个整数,表示最多能少修建多少条新建的道路。
    [样例输入]
    3 2 2
    1 2 1
    2 3 1
    2 2
    3 1
    [样例输出]
    1 

    把所有新加的边去个重,到相同的点的边只保留一个最小的,然后跑一次最短路。一条新加
    的边如果长度不是最短路一定可以去掉,否则只有满足有其它最短路径到达这个点的时候才
    可以去掉。算出到每个点最短路条数是否大等于 2 即可。
    复杂度 O((n+k)logn)

    #include<cstdio>
    #include<cstring>
    struct edge{
        int to,w,nx;
    }e[5000001];
    int q[5000001],he,ta;
    int h[50010],p;
    int n,m,k;
    void ae(int fr,int to,int w){
        e[++p]=(edge){to,w,h[fr]};h[fr]=p;
    }
    long long d[50010];
    int vis[50010],can[50010];
    void spfa(){
        for(int i=1;i<=n;i++) d[i]=0x3f3f3f3f3f3f3f3f;
        d[1]=0;
        q[++ta]=1;
        for(int i=1,x,y;i<=k;i++){
            scanf("%d%d",&x,&y);
            if(d[x]>y){
                d[x]=y,can[x]=1;
                if(vis[x]==0){
                    vis[x]=1;
                    q[++ta]=x;
                }
            }
        }
        while(he<ta){
            int u=q[++he];
            vis[u]=0;
            for(int i=h[u];i;i=e[i].nx){
                int v=e[i].to,dis=e[i].w;
                if(d[v]>=d[u]+dis&&can[v]) can[v]=0;
                if(d[v]>d[u]+dis){
                    d[v]=d[u]+dis;
                    if(vis[v]==0){
                        vis[v]=1;
                        q[++ta]=v;
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)k-=can[i];
        printf("%d
    ",k);
    }
    int main(){
        freopen("road.in","r",stdin);
        freopen("road.out","w",stdout);
        scanf("%d%d%d",&n,&m,&k);
        for(int u,v,w,i=1;i<=m;i++)scanf("%d%d%d",&u,&v,&w),ae(u,v,w),ae(v,u,w);
        spfa();
        return 0;
    }

    爆int爆得好爽。。。

  • 相关阅读:
    uni-app拒绝授权后再次授权
    vue触底操作
    vue滚动条滚到到底部触发的方法
    pagination插件使用例子
    修改后台返回数据的字段
    v-cloak指令的作用
    修改checkbox样式
    获取selected的值
    前端工程师必备的几个实用网站
    html发展史简介(摘抄)
  • 原文地址:https://www.cnblogs.com/nzher/p/7689613.html
Copyright © 2020-2023  润新知