zoukankan      html  css  js  c++  java
  • 记2018/5/5 qbxt 测试

           记2018/5/5 qbxt 测试

      竞赛时间: 2018 年 5 月 5 日 13:30-17:00

    T1  

    一、maze(1s,512MB):

    简单的迷宫问题:给定一个n*m的迷宫,.表示可以通过,#表示不能通过。每一步可以向上下左右的任意方向移动,问是否能够正好k步从s走到t

    输入格式:

      第一行n,m表示迷宫的大小

      接下来n行每行m个字符表示迷宫

      接下来一行五个数字 x1,y1,x2,y2,k 表示起点为(x1,y1) 终点为(x2,y2) 步数为k

    输出格式:

       如果可以正好k步从s走到t输出方案,L表示向左,R表示向右,U表示向上,D表示向下。如果不能输出-1

    样例:

      输入:

      3 3

      …

      .#.

      …

      1 1 3 3 4

      输出:

       RRDD

    数据范围:

       30%的数据满足n,m<=3 保证一定能到

       60%的数据满足 n,m,k<=100

       100%的数据满足 n,m<=1000 k<=1000000

    思路:广搜 or 深搜 + 剪枝

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int n,m,x1,x2,y1,y2,K;
    char c;
    int g[1005][1005],f[1005][1005];
    int q[20000000][3];
    int answer[20000000], dir[1005][1005];
    int main() {
        freopen("maze.in","r",stdin);
        freopen("maze.out","w",stdout);
        scanf("%d %d",&n,&m);
        for (int i = 1; i<=n; i++)
            for (int j = 1; j<=m; j++) {
                scanf(" %c",&c);
                if (c=='.') {
                    g[i][j] = 1;
                } else if (c=='#') {
                    g[i][j] = 0;
                }
                f[i][j] = -1;
            }
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&K);
        if (g[x1][y1] == 0) {
            printf("-1
    ");
            return 0;
        }
        f[x1][y1] = 0;
        q[1][1] = x1;
        q[1][2] = y1;
        for (int s = 1,t = 1; s<=t; s++) {
            int x = q[s][1], y=q[s][2];
            if (x-1>0 && g[x-1][y] == 1 &&f[x-1][y] == -1) {
                f[x-1][y] = f[x][y]+1;
                t++;
                q[t][1] = x-1;
                q[t][2] = y;
                dir[x-1][y] = 1;
            }
            if (x+1<=n && g[x+1][y] == 1 && f[x+1][y] ==-1) {
                f[x+1][y] = f[x][y] +1;
                t++;
                q[t][1] = x+1;
                q[t][2] = y;
                dir[x+1][y] = 2;
            }
            if (y-1>0 && g[x][y-1]==1 && f[x][y-1]  == -1) {
                f[x][y-1] = f[x][y]+1;
                t++;
                q[t][1] = x;
                q[t][2] = y-1;
                dir[x][y-1] = 3;
            }
            if (y+1<=m && g[x][y+1] == 1 &&f[x][y+1] == -1) {
                f[x][y+1] = f[x][y] +1;
                t++;
                q[t][1] = x;
                q[t][2] = y+1;
                dir[x][y+1] = 4;
            }
        }
        if (f[x2][y2] == -1 || (f[x2][y2]+K)%2 == 1 || f[x2][y2]>K) {
            printf("-1
    ");
        } else {
            int x3 = x2, y3 = y2;
            for (int i = 0; x2!=x1 ||y2!=y1; i++) {
                answer[f[x2][y2]] = dir[x2][y2];
                int tmp = dir[x2][y2];
                if (tmp == 1) x2++;
                else if (tmp == 2) x2--;
                else if (tmp==3) y2++;
                else y2--;
            }
            x2 = x3,y2=y3;
            for (int i =0; i<=f[x2][y2]; i++) {
                if (answer[i] == 1) printf("U");
                else if (answer[i] == 2) printf("D");
                else if (answer[i]==3) printf("L");
                else if (answer[i]==4) printf("R");
            }
            for (int i = f[x2][y2]+1; i<=K; i+=2) {
                if (x2+1<=n && g[x2+1][y2]==1) printf("DU");
                else if (x2-1>0 && g[x2-1][y2]==1) printf("UD" );
                else if (y2+1<=m && g[x2][y2+1] == 1) printf("RL");
                else
                    printf("LR");
            }
        }
        return 0;
    }
    标程

    T2

    二、tree(1s,512MB):

    对于一个无根树,他的任意一个联通子图称为他的一个子树。现给出一个无根树,每个节点上有一个权值。 一个子树的权值为这个子树上所有节点权值的xor和。比如子树包含有权值为(1,2,4)的节点,那么子树的权值为 1 xor 2 xor 4 = 7。给定一个无根树求所有子树的权值的和,由于这个数可能很大结果对10^9+7取余。

    输入格式:

      第一行一个整数n表示树的节点数目

      第二行n个整数表示每个节点的权值

      接下来n-1行每行两个树 a,b表示a到b有一条边 (输入保证一定是一个树)

    输出格式:

      一个数 表示所有子树权值的和对10^9+7取余的结果

    样例:

      输入

      3

      1 2 3

      1 2

    1 3

    输出:

    11

    样例解释:

       所有的子树有{1}, {2},{3},{1,2},{1,3},{1,2,3}

       子树的权值为1,    2,  3,   3,     2,    0

       答案为 1+2+3+3+2+0 = 11

    数据范围:

       30%的数据满足 n<=5

       60%的数据满足 n<=100

       100%的数据满足 n<=100000 树上节点的权值为正整数<=10000000000

       其中有40%的数据满足节点权值=0或者1 另有其他10%的数据满足节点权值为1

    思路:Xor可以拆城若干个二进制位 之间互不影响

      考虑一个二进制位:

          随便选一个点为根,f[i][0] 表示以 i 为根的子树 xor 和为 0 的子树个数,f[i][1] 表示以 i 为根的子树xor 和为 1 的子树

        f[i][0] = f[i][0]*(f[son[i]][0] + 1) + f[i][1]*f[son[i][1]]

        f[i][1] = f[i][1]*(f[son[i][0]] + 1) + f[i][0]*f[son[i][1]]

        最后 for 一遍所有的节点 统计答案

        f[fa[i][0]] = f[fa[i]][0]*(f[i][0] + 1) + f[fa[i][1]]*f[i][1]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 300000;
    int fa[maxn],ne[maxn],h[maxn],poi[maxn],q[maxn],vis[maxn];
    long long f[maxn][3];
    int a[maxn];
    int n,tot,x,y;
    int main() {
        freopen("tree.in","r",stdin);
        freopen("tree.out","w",stdout);
        scanf("%d",&n);
        for (int i =1; i<=n; i++)
            scanf("%d",&a[i]);
        for (int i = 0; i<n-1; i++) {
            scanf("%d%d",&x,&y);
            tot++;
            ne[tot] = h[x];
            h[x] = tot;
            poi[tot]= y;
            tot++;
            ne[tot]= h[y];
            h[y] = tot;
            poi[tot]=x;
        }
        q[1] = 1;
        vis[1] = 1;
        for (int s = 1, t = 1; s<=t; s++) {
            int x = q[s];
            for (int j = h[x]; j; j=ne[j])
                if (vis[poi[j]] == 0) {
                    fa[poi[j]] = x;
                    t++;
                    q[t] = poi[j];
                    vis[poi[j]] = 1;
                }
        }
        long long ans = 0;
        for (int t = 31; t>=0; t--) {
            for (int i = 1; i<=n; i++) {
    
                if (a[i]&(1<<t)) f[i][0] = 0, f[i][1] = 1;
                else f[i][0] = 1, f[i][1] = 0;
            }
            for (int i = n; i>=1; i--) {
                int k = q[i];
                int tmp0 = f[fa[k]][0],tmp1 = f[fa[k]][1];
                f[fa[k]][0] = (tmp0*(f[k][0]+1) + tmp1*f[k][1])%1000000007;
                f[fa[k]][1] = (tmp0*f[k][1] + tmp1*(f[k][0]+1))%1000000007;
            }
            for (int i =1; i<=n; i++)
                ans = (ans + f[i][1]*(1LL<<t))%1000000007;
        }
        printf("%lld",ans);
        return 0;
    }
    标程

    T3

    三、number(1s,512MB)

    数字的变化一直是千奇百怪的,于是本题只研究数字的加法和乘法。给定一个数s,每次你能将s变为 s+a 或者 s*b。问最少用几步变为t,无解输出-1

    输入格式:

      四个数 s,t,a,b (s,t为非负整数,a,b为正整数)

    输出格式:

       一个数表示最少的步数

    样例:

       输入

         5 26 3 2

        输出

       3

    样例解释:

       S = 5

       S = S * B = 5*2 = 10

       S = S+A = 5+3 = 13

       S = S*B= 13*2 = 26 = T

       所以只要3步

       数据范围:

          30%的数目满足 s,t,a,b<=100

          60%的数据满足s,t,a,b<=1000000

          100%的数据满足 s,t,a,b<=1000000000000000000

    思路:S = 0, 就是将 T/a  b进制分解将所有的数字加起来

        枚举 x 表示 s 乘了 x 次 b  记结果为 res

        将 ( T-res) / a   b 进制分解,小于 x 位的数字加起来大于等于 x 位的转成十进制加。( T-res) 能够整除a

    #include <cstdio>
    #include <cstring>
    using namespace std;
    long long s,t,a,b;
    int main() {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        scanf("%lld %lld %lld %lld",&s,&t,&a,&b);
        if (b==1) {
            if ((t-s) %a == 0) printf("%lld
    ",(t-s)/a);
            else printf("-1
    ");
            return 0;
        }
        long long ans;
        if ((t-s) %a == 0)
            ans = (t-s)/a ;
        else ans = 1000000000000000003LL;
        for (int i = 1; ; i++) {
            if (t/s < b) break;
            s*=b;
            long long tt = t-s;
            if (tt%a == 0) {
                tt/=a;
                long long ans1 =0;
                for (int j = 1; j<=i; j++) {
                    ans1+=tt%b;
                    tt/=b;
                }
                ans1+=tt+i;
                if (ans1<ans) ans = ans1;
            }
        }
        if (ans != 1000000000000000003) printf("%lld",ans);
        else printf("-1
    ");
    }
    标程

    希望今天前往北京参加APIO的学长学姐以及同级的同学可以考出让自己满意的成绩

      不负初心,继续前进

  • 相关阅读:
    关于32位操作系统和64位操作系统对InstallShield打包的影响
    NEWS: Symantec宣布Wise Package Studio将终止
    InstallShield 2012新功能试用(2) 调用MsiGetProperty等MSI API发生变化
    Basic INFO 在命令行Build InstallShield安装包工程获得压缩安装包
    NEWS InstallShield 2012 Service Pack 1发布
    Basic INFO InstallShield Basic MSI工程中如何在SetupCompleteSuccess界面中启动Readme
    Basic INFO InstallShield的脚本编辑器中如何显示代码行号
    Basic INFO 关于在InstallShield制作的安装包界面中删除InstallShield文字的厂商回复
    Basic INFO InstallShield工程中如何让产品的快捷方式名称始终与产品名保持一致
    Basic INFO: 创建隐藏文件夹
  • 原文地址:https://www.cnblogs.com/v-vip/p/8996235.html
Copyright © 2011-2022 走看看