zoukankan      html  css  js  c++  java
  • 2013 Noip提高组 Day1

    3285 转圈游戏

     

    2013年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。
    游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,第n - m号位置上的小伙伴走到第 0 号位置,第n-m+1 号位置上的小伙伴走到第 1 号位置,……,第 n-1 号位置上的小伙伴顺时针走到第m-1 号位置。
    现在,一共进行了 10^k 轮,请问 x 号小伙伴最后走到了第几号位置。

    输入描述 Input Description

    输入共 1 行,包含 4 个整数 n、m、k、x,每两个整数之间用一个空格隔开。

    输出描述 Output Description

    输出共 1 行,包含 1 个整数,表示 10^k 轮后 x 号小伙伴所在的位置编号。

    样例输入 Sample Input

    10 3 4 5

    样例输出 Sample Output

    5

    数据范围及提示 Data Size & Hint

    对于 30%的数据,0 < k < 7; 
    对于 80%的数据,0 < k < 10^7; 
    对于 100%的数据,1 < n < 1,000,000,0 < m < n,1 <= x <=n,0 < k < 10^9。

    /*
        x小朋友最终位置在(x+10^k * m)%n,用快速幂算出来
    */
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int n,m,k,x;
    int Pow(int a,int b,int p){
        int res=1;
        while(b){
            if(b&1)res=res*a%p;
            a=a*a%p;
            b>>=1;
        }
        return res;
    }
    int main(){
        //freopen("CircleNOIP2013.in","r",stdin);
        //freopen("CircleNOIP2013.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&k,&x);
        int k1=Pow(10,k,n);
        int ans=(x+(m*k1)%n)%n;
        printf("%d",ans);
        return 0;
    }

    3286 火柴排队

     

    2013年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
    ,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
    每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

    输入描述 Input Description

    共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
    第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
    第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

    输出描述 Output Description

    输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。

    样例输入 Sample Input

    [Sample 1]

    2 3 1 4 
    3 2 1 4
    [Sample 2]

    1 3 4 2 
    1 7 2 4

    样例输出 Sample Output

    [Sample 1]
    1
    [Sample 2]
    2

    数据范围及提示 Data Size & Hint

    【样例1说明】
    最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
    【样例2说明】
    最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。
    【数据范围】
    对于 10%的数据, 1 ≤ n ≤ 10; 
    对于 30%的数据,1 ≤ n ≤ 100; 
    对于 60%的数据,1 ≤ n ≤ 1,000; 
    对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ 2^31 - 1。

    /*
        按高度排序后的编号一一对应再求逆序对
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    #define maxn 100010
    int n,c[maxn],tmp[maxn],tot;
    struct node{
        int id,v;
    }a[maxn],b[maxn];
    int cmp(node x,node y){
        return x.v<y.v;
    }
    void sor(int l,int r){
        if(l==r)return;
        int mid=(l+r)>>1;
        sor(l,mid);
        sor(mid+1,r);
        int i=l,p=l,j=mid+1;
        while(i<=mid&&j<=r){
            if(c[i]>c[j])tot+=mid-i+1,tmp[p++]=c[j++];
            else tmp[p++]=c[i++];
            if(tot>=99999997)tot-=99999997;
        }
        while(i<=mid)tmp[p++]=c[i++];
        while(j<=r)tmp[p++]=c[j++];
        for(int i=l;i<=r;i++)c[i]=tmp[i];
    }
    int main(){
        freopen("MatchNOIP2013.in","r",stdin);
        freopen("MatchNOIP2013.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i].v),a[i].id=i;
        for(int i=1;i<=n;i++)scanf("%d",&b[i].v),b[i].id=i;
        sort(a+1,a+n+1,cmp);
        sort(b+1,b+n+1,cmp);
        for(int i=1;i<=n;i++)c[a[i].id]=b[i].id;
        sor(1,n);
        printf("%d",tot);
    }

    3287 货车运输

     

    2013年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    输入描述 Input Description

    第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
    接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
    接下来一行有一个整数 q,表示有 q 辆货车需要运货。
    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

    输出描述 Output Description

    输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

    样例输入 Sample Input

    4 3 
    1 2 4 
    2 3 3 
    3 1 1 
    3
    1 3 
    1 4 
    1 3

    样例输出 Sample Output

    3
    -1
    3

    数据范围及提示 Data Size & Hint

    对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000; 
    对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000; 
    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

    /*
        首先,可以证明,所有货车都可以只在最大生成树上跑,并不影响答案。(考虑到最大生成树的定义)
        求出最大生成树后,问题转化为,q个询问,每个询问问一条路径上的最小边权。
        可以用倍增来做。预处理f[u][k](意义同LCA中),l[u][k]表示u到u的2^k级祖先的路径上最小的边权值。
        可以在求LCA的过程中直接求出路径上的最小边权。
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 10010
    #define maxm 50010
    int n,m,f[maxn][20],sum[maxn][20],fa[maxn],num,p,dep[maxn],head[maxn]; 
    bool vis[maxn];
    struct node{
        int f,to,v;
    }a[maxm];
    struct Edge{
        int pre,v,to;
    }e[maxm];
    int cmp(node x,node y){return x.v>y.v;}
    int find(int x){
        if(fa[x]==x)return fa[x];
        else return fa[x]=find(fa[x]);
    }
    int connect(int x,int y){
        int f1=find(x),f2=find(y);
        if(f1==f2)return 0;
        else fa[f1]=f2;return 1;
    }
    void Insert(int from,int to,int v){
        e[++num].v=v;
        e[num].to=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    void dfs(int now,int father,int deep){
        vis[now]=1;
        dep[now]=deep;
        for(int i=head[now];i;i=e[i].pre){
            int v=e[i].to;
            if(v==father)continue;
            f[v][0]=now;
            sum[v][0]=e[i].v;
            dfs(v,now,deep+1);
        }
    }
    int lca(int x,int y){
        if(x==y)return 0;
        int ans=0x3f3f3f3f;
        if(dep[x]<dep[y])swap(x,y);
        for(int i=18;i>=0;i--){
            if(dep[f[x][i]]>=dep[y]&&f[x][i]!=0)ans=min(ans,sum[x][i]),x=f[x][i];
        }
        if(x==y)return ans;
        for(int i=18;i>=0;i--){
            if(f[x][i]!=f[y][i]){
                ans=min(ans,sum[x][i]);
                ans=min(ans,sum[y][i]);
                x=f[x][i];y=f[y][i];
            }
        }
        ans=min(sum[x][0],ans);ans=min(sum[y][0],ans);
        return ans;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("truck.in","r",stdin);
        freopen("truck.out","w",stdout);
        memset(sum,127/3,sizeof(sum));
        int x,y,z;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].f,&a[i].to,&a[i].v);
        for(int i=1;i<=n;i++)fa[i]=i;
        sort(a+1,a+m+1,cmp);int cnt=0;
        for(int i=1;i<=m;i++){
            if(connect(a[i].f,a[i].to)){
                Insert(a[i].f,a[i].to,a[i].v);
                Insert(a[i].to,a[i].f,a[i].v);
                cnt++;if(cnt==n-1)break;
            }
        }
        for(int i=1;i<=n;i++)if(!vis[i])dfs(i,0,1);
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i<=n;i++)
                if(f[f[i][j-1]][j-1]!=0){
                    f[i][j]=f[f[i][j-1]][j-1];
                    sum[i][j]=min(sum[i][j-1],sum[f[i][j-1]][j-1]);
                }
        scanf("%d",&p);
        for(int i=1;i<=p;i++){
            scanf("%d%d",&x,&y);
            if(find(x)!=find(y)){printf("-1
    ");continue;}
            printf("%d
    ",lca(x,y));
        }
    }
  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    41. First Missing Positive
    40. Combination Sum II
    39. Combination Sum
  • 原文地址:https://www.cnblogs.com/thmyl/p/7243326.html
Copyright © 2011-2022 走看看