• restart 1018模拟赛


    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

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

    二分也可以做,只不过复杂度较高。

    #include<iostream>
    #include<cstdio>
    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;
    }
    int n,m,k;long long ans=0;
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        n=read();m=read();k=read();
        if(n+m-2<k) return 0*puts("-1"); 
        for(int i=1,last;i<=n;i=last+1)
        {
            last=n/(n/i);int j=min(last,k+1);
            if(j>=i) ans=max(ans,1LL*(n/j)*(m/(k-(j-1)+1)));
        }
        printf("%lld
    ",ans);
        return 0;
    }

    T2.小 Z 爱数组(array)

    小 Z 最喜欢数组了,现在他得到了由 n 个正整数组成的数组 ai,他想构造
    一个相同大小的正整数数组 bi 满足两个数组的差异度∑abs(ai-bi)
    最小。 特殊的
    是,bi 数组的所有元素必须满足两两互质。
    [输入格式]
    从 array.in 中读取数据。
    第一行一个数 n,表示数组大小。
    接下来一行 n 个正整数 ai,表示给定的数组。
    [输出格式]
    输出一行 n 个正整数 bi,表示答案。
    输出的数字必须满足 1<=bi<=10^9。如果有多个答案,你可以输出任意一个。
    [样例输入]
    5
    1 6 4 2 8
    [样例输出]
    1 5 4 1 9
    [样例解释]
    差异度为 3,可以证明是最小的差异度。还有其它可行的方案。

    [数据范围与约定]
    本题采用子任务制,你只有通过一个子任务所有的数据才能得到对应的分数。
    Subtask1:包含 20Points,满足 n<=8 1<=ai<=5
    Subtask2:包含 30Points,满足 n<=50 1<=ai<=15
    Subtask3:包含 50Points,满足 n<=100 1<=ai<=30

    t2真的难,所以贴标程。

    原题 ai 不超过 30,所以选择的 bi 肯定小于 59,不然可以用 1 代替。

    #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;    
    }

    58 以内只有 16 个质数,所以将这些质数的状态压起来之后 dp 即可,复杂度 O(2^16*n*58)

    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
    [数据范围与约定]
    对于 20%的数据,满足 n,m,k<=100
    对于另外 20%的数据,满足 k<=4
    对于 100%的数据,满足 n,k<=50000 , m<=200000 , 1<=ti,wi<=10^9 , si>=2

    solution:

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

    注意去重!!

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define pa pair<long long,int>
    #define MN 100000
    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;
    }
    priority_queue<pa,vector<pa>,greater<pa> >q;
    int n,m,K,head[MN+5],cnt=0,mn[MN+5],ans=0;long long d[MN+5],num[MN+5];
    struct edge{int to,next,w;}e[MN*8+5];
    
    inline void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;    
        e[++cnt]=(edge){f,head[t],w};head[t]=cnt;
    }
    
    void Dij()
    {
        memset(d,63,sizeof(d));q.push(make_pair(d[1]=0,1));num[1]=1;
        while(!q.empty())
        {
            while(!q.empty()&&d[q.top().second]!=q.top().first) q.pop();
            if(q.empty()) return;
            int x=q.top().second;q.pop();
            for(int i=head[x];i;i=e[i].next)
                if(d[x]+e[i].w<d[e[i].to]) q.push(make_pair(d[e[i].to]=d[x]+e[i].w,e[i].to)),num[e[i].to]=num[x];    
                else if(d[x]+e[i].w==d[e[i].to]) num[e[i].to]=min(num[e[i].to]+num[x],(long long)1e9);
        }
    }
  • 相关阅读:
    IfcSameDirection
    IfcSameCartesianPoint
    java多个文件合并为一个文件
    matlab pan_tompkin算法
    IfcSameAxis2Placement
    IfcOrthogonalComplement
    IfcNormalise
    IfcMakeArrayOfArray
    matlab 日期 年月日时分秒毫秒
    IfcListToArray
  • 原文地址:https://www.cnblogs.com/qizhengquan/p/7691990.html
Copyright © 2020-2023  润新知