• 9.18模拟赛


    完美的序列(sequence)

    题目描述

    LYK认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同。然而并不是所有的序列都满足这样的条件。

    于是LYK想将序列上的每一个元素都增加一些数字(当然也可以选择不增加),使得整个序列变成美妙的序列。

    具体地,LYK可以花费 11 点代价将第 ii 个位置上的数增加 11 ,现在LYK想花费最小的代价使得将这个序列变成完美的序列。

    输入输出格式

    输入格式:

     

    第一行一个数nn,表示数字个数。

    接下来一行nn个数a_iai​​表示LYK得到的序列。

     

    输出格式:

     

    一个数表示变成完美的序列的最小代价。

     

    输入输出样例

    输入样例#1:
    4
    1 1 3 2
    输出样例#1:
    3

    说明

    对于30\%30%的数据n leq 5n5。

    对于60\%60%的数据n leq 1000n1000。

    对于80\%80%的数据n leq 30000n30000,a_i leq 3000ai​​3000。

    对于100\%100%的数据n leq 100000n100000,1leq a_i leq 1000001ai​​100000。

     题解:

    80分贪心..每次加到最小的没有出现的....

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    int n,ans,a[100005],apper[100005];
    
    int main(){
        freopen("sequence.in","r",stdin);
        freopen("sequence.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++){
            if(apper[a[i]]==0){
                apper[a[i]]=1;
                continue;
            }   
            while(apper[a[i]]){
                ans++;a[i]++;
            }
            apper[a[i]]=1;
        }
        printf("%d
    ",ans);
        fclose(stdin);fclose(stdout);
        return 0;
    }

    正解:贪心...从小到大排序..最后的序列一定是一个递增的...每次加到刚刚好就可以

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxn 100006
    using namespace std;
    int n,a[maxn];
    long long ans;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        for(int i=2;i<=n;i++){
            if(a[i]<=a[i-1]){
                ans+=(a[i-1]-a[i]+1);
                a[i]=a[i-1]+1;
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    LYK与实验室(lab)

    题目描述

    LYK在一幢大楼里,这幢大楼共有 nn 层,LYK初始时在第 aa 层上。

    这幢大楼有一个秘密实验室,在第 bb 层,这个实验室非常特别,对LYK具有约束作用,即若LYK当前处于 xx 层,当它下一步想到达 yy 层时,必须满足 |x-y|<|x-b|xy<xb∣,而且由于实验室是不对外开放的,电梯无法停留在第bb层。 LYK想做一次旅行,即它想按 kk 次电梯,它想知道不同的旅行方案个数有多少个。

    两个旅行方案不同当前仅当存在某一次按下电梯后停留的楼层不同。

    输入输出格式

    输入格式:

     

    一行4个数,n,a,b,kn,a,b,k。

     

    输出格式:

     

    一个数表示答案,由于答案较大,将答案对10000000071000000007取模后输出。

     

    输入输出样例

    输入样例#1:
    5 2 4 1
    输出样例#1:
    2
    输入样例#2:
    5 2 4 2
    输出样例#2:
    2
    输入样例#3:
    5 3 4 1
    输出样例#3:
    0

    说明

    对于20\%20%的数据n,kleq 5n,k5。

    对于40\%40%的数据n,kleq 10n,k10。

    对于60\%60%的数据n,kleq 500n,k500。

    对于90\%90%的数据n,k leq 2000n,k2000。

    对于100\%100%的数据n,k leq 5000n,k5000。

     题解:

    40分 暴力搜索

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define mod 1000000007LL
    using namespace std;
    
    long long ans;
    int n,a,b,g;
    
    void dfs(int now,int k){
        if(now==b)return;
        if(k==g){
            ans++;
            ans=ans%mod;
            return;
        }
        for(int i=now-1;i>=1;i--){
            if(abs(now-i)<abs(now-b))
            dfs(i,k+1);
            else break;
        }
        for(int i=now+1;i<=n;i++){
            if(abs(now-i)<abs(now-b))
            dfs(i,k+1);
        }
    }
    
    int main(){
        freopen("lab.in","r",stdin);
        freopen("lab.out","w",stdout);
        scanf("%d%d%d%d",&n,&a,&b,&g);
        //n层电梯 开始在a层 实验室在b层 按g次电梯。
        dfs(a,0); 
        cout<<ans<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    60分O(n^3)dp

    f[i][j]表示摁k次到达j的情况总数....

    转移方程:f[i][j]+f[i-1][l]....l是能到达j的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 1000000007LL
    using namespace std;
    int n,a,b,k;
    long long ans;
    int f[2001][2001];
    int zs(int x){
        if(x<0)return -x;
        return x;
    }
    int main(){
        scanf("%d%d%d%d",&n,&a,&b,&k);
        f[0][a]=1;
        for(int i=1;i<=k;i++){
            for(int j=1;j<=n;j++){
                if(j==b)continue;
                for(int l=1;l<=n;l++){
                    if(l==b||l==j)continue;
                    if(zs(l-j)<zs(l-b)){
                        f[i][j]=f[i][j]+f[i-1][l];
                        f[i][j]%=mod;
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)ans=(ans%mod+f[k][i]%mod)%mod;
        cout<<ans<<endl;
        return 0;
    }

    100分 前缀和优化+压维

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #define N 5010
    #define mod 1000000007
    using namespace std;
    int n,a,b,m,dp[2][N],s[2][N];
    int main() {
        scanf("%d%d%d%d",&n,&a,&b,&m);
        dp[0][a]=1;
        for(int i=a;i<=n;i++)s[0][i]=1;
        for(int i=1;i<=m;i++)
          for(int j=1;j<=n;j++) {
              int limit;
              if(j>b)limit=j-(j-b-1)/2,
              dp[i%2][j]=((s[(i+1)%2][n]-s[(i+1)%2][j-(j-b-1)/2-1]-dp[(i+1)%2][j])%mod+mod)%mod;
              if(j<b)limit=j+(b-j-1)/2,
              dp[i%2][j]=((s[(i+1)%2][j+(b-j-1)/2]-dp[(i+1)%2][j])%mod+mod)%mod;
              s[i%2][j]=(s[i%2][j-1]+dp[i%2][j])%mod;
          }
        int ans=0;
        for(int i=1;i<=n;i++)
          ans+=dp[m%2][i],ans%=mod;
        printf("%d",ans);
        return 0;
    }

    旅行(travel)

    题目描述

    LYK想去一个国家旅行。这个国家共有 nn 个城市,有些城市之间存在道路,我们假定这些道路长度都是 11 的,更准确的说,共有 mm 条道路。

    我们定义城市AA与城市BB的最短路为AA到BB的所有路径中,经过的道路最少的那条道路。最短路的长度为这条道路的所有道路长度之和,由于所有道路长度都为 11,因此假如AA到BB之间最短路的道路条数为 kk,则A到B的最短路长度为 kk。

    我们定义整个国家的最短路为任意两个城市(A,BA,B与B,AB,A算作不同的点对)之间的最短路长度的和。

    然而这个国家正处于危乱之中,极有可能一条道路会被恐怖分子炸毁。

    LYK想知道,万一某条道路被炸毁了,整个国家的最短路为多少。若炸毁这条道路后整个国家不连通了,那么就输出“INF”(不加引号)。

    输入输出格式

    输入格式:

     

    第一行两个数n,mn,m。

    接下来mm行,每行两个数u,vu,v,表示存在一条道路连接u,vu,v(数据保证不存在自环)。

     

    输出格式:

     

    输出mm行,第 ii 行的值表示当第i条道路被炸毁时,整个国家的最短路是多少,若图不连通,则输出“INF”。

     

    输入输出样例

    输入样例#1:
    2 2
    1 2
    1 2
    输出样例#1:
    2
    2

    说明

    对于20\%20%的数据n leq 10,n leq mleq100n10,nm100。

    对于40\%40%的数据1leq n<m leq 1001n<m100。

    对于70\%70%的数据1leq n leq 100,n<m leq 30001n100,n<m3000。

    对于再另外10\%10%的数据对于所有节点i(1leq i < n)i(1i<n),存在一条边连接 ii 与i+1i+1,且n=mn=m,n leq 100n100。

    对于再另外10\%10%的数据对于所有节点i(1leq i < n)i(1i<n),存在一条边连接 ii 与i+1i+1,且n=mn=m,n leq 1000n1000。

    对于再另外10\%10%的数据对于所有节点i(1leq i < n)i(1i<n),存在一条边连接 ii 与i+1i+1,且n=mn=m,n leq 100000n100000。

    题解:暴力30分

    每次切边然后弗洛伊德....时间复杂度... mn^3.....

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int n,m,ans;
    int f[333][333],d[333][333];
    
    struct WW {
        int x,y;
    } e[3002];
    void cut(int ii) {
        int x=e[ii].x,y=e[ii].y;
        f[x][y]--;
        f[y][x]--;
    }
    void huifu(int ii) {
        int x=e[ii].x,y=e[ii].y;
        f[x][y]++;
        f[y][x]++;
    }
    
    /*void debug(){
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                cout<<i<<" "<<j<<" "<<d[i][j]<<endl;
            }
        }
    }*/
    
    void floyed() {
        int flag=0;
        memset(d,0x3f,sizeof(d));
        for(int i=1; i<=n; i++) {
            d[i][i]=0;
            for(int j=i+1; j<=n; j++) {
                if(f[i][j])d[i][j]=d[j][i]=1;
            }
        }
        for(int k=1; k<=n; k++)
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    //    debug();
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++)
                if(d[i][j]==0x3f3f3f3f) {
                    flag=1;
                    break;
                } else ans+=d[i][j];
            if(flag) {
                printf("INF
    ");
                break;
            }
        }
        if(flag==0) {
            printf("%d
    ",ans);
        }
    }
    int main() {
        freopen("travel.in","r",stdin);
        freopen("travel.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++) {
            scanf("%d%d",&e[i].x,&e[i].y);
            int x=e[i].x,y=e[i].y;
            f[x][y]++;
            f[y][x]++;
        }
        for(int i=1; i<=m; i++) {
            ans=0;
            cut(i);
            floyed();
            huifu(i);
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    正解:先bfs计算出每个点到某个点的最短路径,然后枚举删边..如果删的这条边在

    最短路上那么就重新求这个最短路...正解容斥原理..弃疗...

    code 50分

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define LL long long
    #define inf 100000000
    #define maxn 3005
    using namespace std;
    queue<int>q;
    int n,m,sumedge;
    LL ans;
    int head[maxn],dis[maxn],inq[maxn],pre[maxn][maxn],sum[maxn];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<2];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void bfs(int st){
        while(!q.empty())q.pop();
        memset(dis,0,sizeof(dis));
        memset(inq,0,sizeof(inq));
        inq[st]=1;q.push(st); 
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=head[now];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(inq[v]==0){
                    inq[v]=1;
                    pre[st][v]=now;
                    dis[v]=dis[now]+1;
                    q.push(v); 
                }
            }
        }
        for(int i=1;i<=n;i++)sum[st]+=dis[i];
    }
    
    void spfa(int st,int cutedge){
        memset(inq,0,sizeof(inq));
        for(int i=1;i<=n;i++)dis[i]=inf;
        dis[st]=0;inq[st]=1;
        while(!q.empty())q.pop();
        q.push(st);
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=head[now];i;i=edge[i].nxt){
                if(i==cutedge||i==cutedge+1)continue;
                int v=edge[i].y;
                if(inq[v]==0){
                   dis[v]=dis[now]+1;
                   inq[v]=1;
                   q.push(v); 
                }
            }
        } 
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        for(int i=1;i<=n;i++)bfs(i);
        for(int i=1;i<=m*2;i+=2){
            int u=edge[i].x,v=edge[i].y;
            LL ans=0;
            for(int j=1;j<=n;j++){
                if(pre[j][u]==v||pre[j][v]==u){
                    spfa(j,i);
                    for(int k=1;k<=n;k++)ans+=dis[k];
                }else ans+=sum[j];
            }
            if(ans<inf){
                cout<<ans<<endl;
            }else printf("INF
    ");
        }
        return 0;
    }
  • 相关阅读:
    jdbc连接池工具与pg fdw连接的问题
    关于drill http存储插件http 超时的一些说明
    tds-fdw PostgreSQL said: DB-Library error: DB #: 20002, DB Msg: Adaptive Server connection failed, OS #: 0, OS Msg: Success, Level: 9 问题解决.md
    开发自己的jdbc驱动——可选开发工具
    nexus Invalid state: DELETED; allowed: [STARTED] 问题解决
    airline开发类似git cli 的jar 包
    开发自己的jdbc驱动——基本说明
    nessie 安装&&简单试用
    nessie 类似git 管理数据湖
    一些不错的开源大数据虚拟数据sql 查询引擎
  • 原文地址:https://www.cnblogs.com/zzyh/p/7553149.html
Copyright © 2020-2023  润新知