• SHU 2013 暑期集训(7-16)解题报告


    来补解题报告。

    Problem A: 【C语言训练】求具有abcd=(ab+cd)^2性质的四位数
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 37 Solved: 37
    [Submit][Status][Web Board]
    Description
    3025这个数具有一种独特的性质:将它平分为二段,即30和25,使之相加后求平方,即(30+25)2,恰好等于3025本身。请求出具有这样性质的全部四位数

    Input
    Output
    满足题意的数全部四位数(从小到大输出,且数之间用两个空格分开)
    Sample Input
    Sample Output
    2025 3025 9801
    HINT
    根据题意可以采用穷举法,对所有四位数进行判断,从而筛选出符合这种性质的四位数。具体算法实现,可任取一个四位数,将其截为两部分,前两位为a,后两位为b,然后套用公式计算并判断。

    [Submit][Status][Web Board]

    不写了,答案就是样例上面的了。

    Problem B: VIJOS-P1237
    Time Limit: 2 Sec Memory Limit: 128 MB
    Submit: 101 Solved: 12
    [Submit][Status][Web Board]
    Description
    天使告诉小杉,每只翅膀都有长度,两只翅膀的长度之比越接近黄金分割比例,就越完美。 现在天使给了小杉N只翅膀,小杉想挑出一对最完美的。
    Input
    每组测试数据的 第一行有一个数N(2< =N< =30000) 第二行有N个不超过1e5的正整数,表示N只翅膀的长度。 20%的数据N< =100
    Output
    对每组测试数据输出两个整数,表示小杉挑选出来的一对翅膀。 注意,比较短的在前,如果有多对翅膀的完美程度一样,请输出最小的一对。
    Sample Input
    4
    2 3 4 6
    Sample Output
    2
    3
    HINT
    你可以认为黄金分割比就是0.6180339887498949

    题目大意:不用多说,给你n个数,要求挑出两个数使得两者之比最接近黄金分割。

    分析:首先当然要按大小先排个序,然后维护一个最接近黄金比例的结果就可以了,采用类似于二分的思想。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define st 0.6180339887498949
     7 #define maxlen 30010
     8 using namespace std;
     9 int num[maxlen];
    10 double myabs(double x)
    11 {
    12     return x<0?-x:x;
    13 }
    14 int main()
    15 {
    16     int n;
    17     while(scanf("%d",&n)!=EOF)
    18     {
    19         int s=1,e=2;
    20         double minc=1000;
    21         int mina,minb;
    22         for (int i=1; i<=n; i++)
    23             scanf("%d",&num[i]);
    24         sort(num,num+n);
    25         while(e<=n)
    26         {
    27             if (myabs(num[s]*1.0/num[e]-st)<minc)
    28             {
    29                 mina=num[s];
    30                 minb=num[e];
    31                 minc=myabs(num[s]*1.0/num[e]-st);
    32             }
    33             if (myabs(num[s]*1.0/num[e])<st)
    34                 s++;
    35             else
    36                 e++;
    37         }
    38         printf("%d
    %d
    ",mina,minb);
    39     }
    40     return 0;
    41 }
    View Code

    Problem C: 多项式构造问题
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 58 Solved: 14
    [Submit][Status][Web Board]
    Description
    给你 9个整数,分别是 x的 8次方至 次方至 0次方的系数,请按照多项式一般形合理地构造。规则如 下:
    1. 多项式的必须按其指数从高到低排列
    2. 指数必须跟在符号“ ^”后显示
    3. 有常数 的只显示常数项
    4. 只显示系数不为 0的项;系数全 0,需显示常数项
    5. 项与间的加号或减两边需上空格
    6. 首项是正系数,其前不加符号否则负与间空格
    7. 负系数的项
    要显示成减一个正8. 系数是 1,指数为 0时,系数的 1才显示 。

    Input
    有 若干个行,每一上9个系数,间有空格隔开的绝对值为小于 1000的整数。

    Output
    对输入中的每一行系数,出应多项式 个。

    Sample Input
    0 0 0 1 22 –333 0 1 –1
    0 0 0 0 0 0 –55 5 0
    Sample Output
    x^5 + 22x^4 – 333x^3 + x – 1
    -55x^2 + 5x

    分析:纯模拟题,就是细节比较多,需要注意一下。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int a[10];
     6 void Print()
     7 {
     8     int j=0;
     9     while (a[j]==0 && j<8)
    10         ++j;
    11     bool flag=false;
    12     if (j==8)
    13         flag=true;
    14     if (j!=8)
    15     {
    16         if (a[j]<0)
    17         {
    18             printf("-");
    19             a[j]*=-1;
    20         }
    21         if (a[j]>1)
    22         {
    23             if (j<7) printf("%dx^%d",a[j],8-j);
    24             if (j==7) printf("%dx",a[j]);
    25         }
    26         else
    27         {
    28             if (j<7) printf("x^%d",8-j);
    29             if (j==7) printf("x");
    30         }
    31     }
    32     if (j!=8) ++j;
    33     while (j<8)
    34     {
    35         while (a[j]==0)
    36             ++j;
    37         if (j>=8) break;
    38         printf(" ");
    39         if (a[j]>0)
    40             printf("+ ");
    41         else
    42         {
    43             printf("- ");
    44             a[j]*=-1;
    45         }
    46         if (a[j]>1)
    47         {
    48             if (j<7)
    49                 printf("%dx^%d",a[j],8-j);
    50             if (j==7)
    51                 printf("%dx",a[j]);
    52         }
    53         else
    54         {
    55             if (j<7)
    56                 printf("x^%d",8-j);
    57             if (j==7)
    58                 printf("x");
    59         }
    60         ++j;
    61     }
    62     if (a[j]!=0)
    63     {
    64         if (!flag)
    65             printf(" ");
    66         if (!flag && a[j]>0)
    67             printf("+");
    68         if (a[j]<0)
    69         {
    70             printf("-");
    71             a[j]*=-1;
    72         }
    73         if (!flag) printf(" ");
    74         printf("%d",a[j]);
    75     }
    76     else if (flag)
    77         printf("0");
    78     printf("
    ");
    79 }
    80  
    81 int main()
    82 {
    83     while (scanf("%d",&a[0])!=EOF)
    84     {
    85         for(int i=1;i<9;++i)
    86         scanf("%d",&a[i]);
    87         Print();
    88     }
    89 }
    View Code

    Problem D: 三角迷宫
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 22 Solved: 12
    [Submit][Status][Web Board]
    Description
    这里有45个数字组成的一个三角阵,数字分别是1、2、3、...、9不等。要求你每次从顶点A处开始,一步步地通过它相邻的数字走到对边为止:但是一定要全部通过1,2,3,....,9这些数字,缺一不可,顺序不限,也不得重复,更不许走回头路。
    A 1
    3 6
    9 7 8
    2 6 3 9
    3 1 5 8 5
    5 9 4 6 3 2
    8 3 2 9 4 9 1
    6 5 7 4 1 2 8 7
    7 1 4 8 7 4 5 6 2
    对上述三角迷宫,我们可以找到一条路线,A 处:139654278。你能找出这一条路线来吗?

    Input
    输入有若干组测试数据,其第一行是整数n,表示三角迷宫的个数。接着有n 组测试数据,每一组是一个三角迷宫的描述,共9 行,第i 行上有i 个1 到9 之间的数字符号,i=1,2,„,9,每行上的数字符号之间有一个空格。两个三角迷宫之间有一个空行。

    Output
    对输入中描述的每组三角迷宫,确定从顶点A 出发,可否一步步地通过它相邻的数字走到对边为止,使路径上包含1,2,3„9 这全部9 个数字,顺序不限,不要重复,不许走回头路。先输出“Case#:”,其中“#”是三角迷宫的组号。如果从该顶点出发,可以确定这样的路线,则在下一行上输出“Possible”,否则输出“Impossible”。

    Sample Input
    2
    1
    3 6
    9 7 8
    2 6 3 9
    3 1 5 8 5
    5 9 4 6 3 2
    8 3 2 9 4 9 1
    6 5 7 4 1 2 8 7
    7 1 4 8 7 4 5 6 2

    4
    3 6
    9 7 8
    2 6 3 9
    3 1 5 8 5
    5 9 4 6 3 2
    8 3 2 9 4 9 1
    6 5 7 4 1 2 8 7
    7 1 4 8 7 4 5 6 2
    Sample Output
    Case 1:
    Possible
    Case 2:
    Impossible
    HINT

    题目大意:从最顶端开始向下走,每次只能走当前位置相邻的位置么不能往回走,问能不能走过所有的9个数字(1-9)

    分析:训练的时候没有写这个题目,应该就是深搜下去,递归到最后一层的时候判断一下9个数字是不是都走过来。状态数量不多。

    Problem E: 分型Time Limit: 1 Sec Memory Limit: 128 MB

    Submit: 29 Solved: 9
    [Submit][Status][Web Board]
    Description
    分形在一定的技术意义上说,是在所有标度显示自相似性的一个对象或数量。对象不必在所有标度上展示完全相同的结构,但在所有标度上显示同样的结构“类型”。
    分型块的定义如下:
    次数是1的分型块只是:
    X
    次数2的分型块是:
    X X
    X
    X X
    如果利用B(n-1)表示次数是n-1的分型块,那么次数是n的分型块递归定义如下:
    B(n-1) B(n-1)
    B(n-1)
    B(n-1) B(n-1)
    你的任务是画一个次数是n的分型块。
    Input
    输入有多组测试数据。每行有一个不大于7的正整数n 。最后一行的一个负整数-1表示输入结束。
    Output
    对每组测试数据,输出用大写字母‘X’标记的分型块。每组测试数据后输出一个破折号。尾部无多余空格。
    Sample Input
    1
    2
    -1
    Sample Output
    X
    -
    X  X
      X
    X  X
    -
    HINT

    题目大意:没什么好说的,打印图形。

    分析:题目已经给提示需要进行分治,把图形分为5各部分,每个部分都是一样的,递归到下一层,一直到规模只有1时直接打印即可。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define  maxlen 3000
     5 using namespace std;
     6 char maps[maxlen][maxlen];
     7 int mypow(int x,int n)
     8 {
     9     int ans=1;
    10     for(int i=0; i<n; ++i)
    11     {
    12         ans*=x;
    13     }
    14     return ans;
    15 }
    16 void Print(int x,int y ,int s)
    17 {
    18     if(s==1)
    19     {
    20         maps[x][y]='X';
    21         return ;
    22     }
    23     int k=mypow(3,s-2);
    24     Print(x,y,s-1);
    25     Print(x,y+k*2,s-1);
    26     Print(x+k,y+k,s-1);
    27     Print(x+2*k,y,s-1);
    28     Print(x+2*k,y+2*k,s-1);
    29 }
    30 int main ()
    31 {
    32     int n;
    33     while(scanf("%d",&n)!=EOF)
    34     {
    35         if(n==-1)
    36             break;
    37         memset(maps,' ',sizeof(maps));
    38         int k=mypow(3,n-1);
    39         Print(0,0,n);
    40         for(int i=0; i<k; ++i)
    41         {
    42             int pos;
    43             for(pos=k-1;pos>=0;--pos)
    44             {
    45                 if(maps[i][pos]=='X')
    46                     break;
    47             }
    48             for(int j=0;j<=pos;++j)
    49                 cout<<maps[i][j];
    50             cout<<endl;
    51 
    52         }
    53         printf("-
    ");
    54     }
    55 }
    View Code

    Problem F: 无向图的连通分支
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 24 Solved: 15
    [Submit][Status][Web Board]
    Description
    输入一个无向图G,计算G的连通分支数。

    Input
    有多个无向图数据。每个无向描述的第1行是两个整数n和e,分别表示顶点数和边数。接着有e行,每行有2个整数a、b,分别是一条边的两个端点(起点和终点)。两个图之间空一行。

    Output
    对每个无向图,输出图中连通分支个数。

    Sample Input
    2 1
    1 2

    5 8
    1 2
    1 3
    1 4
    1 5
    2 3
    2 4
    3 4
    4 5
    Sample Output
    1
    1
    HINT

    题目大意:求无向图连通分支数。

    分析:枚举每个没有搜索过的顶点(没枚举一个计数器+1),dfs搜索整个图,标记搜索过的结点,最后输出答案就可以了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxlen 1100
     5 using namespace std;
     6 bool maps[maxlen][maxlen];
     7 int visited[maxlen];
     8 int n,m;
     9 void dfs(int i)
    10 {
    11     if(visited[i])
    12         return ;
    13     visited[i]=true;
    14     for(int j=1;j<=n;++j)
    15     {
    16         if(maps[i][j]==true&&!visited[j])
    17         {
    18             dfs(j);
    19         }
    20     }
    21 }
    22 int main ()
    23 {
    24     int a,b;
    25     while(scanf("%d%d",&n,&m)!=EOF)
    26     {
    27         for(int i=0;i<=n;++i)
    28         for(int j=0;j<=n;++j)
    29         {
    30             if(i==j)
    31                 maps[i][j]=1;
    32             else
    33                 maps[i][j]=0;
    34         }
    35         for(int i=0;i<m;++i)
    36         {
    37             scanf("%d%d",&a,&b);
    38             maps[a][b]=maps[b][a]=true;
    39         }
    40         memset(visited,0,sizeof(visited));
    41         int ans=0;
    42         for(int i=1;i<=n;++i)
    43         {
    44             if(!visited[i])
    45             {
    46                 dfs(i);
    47                 ans++;
    48             }
    49         }
    50        printf("%d
    ",ans);
    51     }
    52 }
    View Code

    Problem G: 奇异的结构
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 14 Solved: 9
    [Submit][Status][Web Board]
    Description
    设k³0。有0、1序列组成的2k×2k阵列表示的图像,其中用0表示白,用1表示黑。

    图12 0-1阵列图像

    现在通过如下方式对黑白图像进行分割,构造一棵四叉树:

    黑白图象划分

    (1)如子图像不是全白或全黑,将它分割为四等分。

    (2)从左上、右上、左下、右下依次对各子图像依次进行编号。

    四叉树构造

    (1)树中叶结点由白色或黑色标记。

    (2)非叶子结点的四个子结点的顺序依次为左上、右上、左下、右下。

    (3)四叉树由表示从黑叶结点到根结点路径的数字序列表示。

    (4)每条路径是一个5进制数。

    图12- 四叉树及结点编号

    首先看图12- (A)的0-1图像。由于图像不全白也不全黑,因此进行分割,分成左上、右上、左下、右下四个部分。由于左上部分已是全白的,不必再分割。对右上部分需再分割成四小部分。此时这四小部分均已无法分割。再对其它部分进行处理。现在看结点情况,右上部分经第二次分割后的左下角的结点,其编号应为32,在四叉树中对应的结点为4号。

    4号结点对应的五进制数为(32)5=(17)10;12号结点对应的五进制数为(43)5=(23)10;

    15号结点对应的五进制数为(134)5=(44)10

    四叉树中黑结点共11个,这些黑结点对应的十进制表示为:9、14、17、22、23、44、63、69、88、94、113。这也称为图像的十进制表示。

    现在你的任务是根据一个0-1图像,求图像的十进制表示;反过来,根据图像的十进制表示,求对应的0-1图像。

    Input
    有多组测试数据。每组的第1行是一个整数n,n可正可负,其绝对值m是2的幂。如n为正,那么接下来有n行,每行有n个0或1构成的字符串,这些表示一个0-1图像。如果n为负数,那么下面有若干以-1结尾的整数,前面的整数均为非负整数,表示图像的十进制表示。当n=0时表示输入结束。

    Output
    对每组测试数据,先输出测试数据编号(从1开始)。在接下来的行上,如果是一个0-1图像,那么以升序方式输出对应图像的十进制表示;如果输入是图像的十进制表示,那么输出图像的0-1表示。

    Sample Input
    8
    00000000
    00000000
    00001111
    00001111
    00011111
    00111111
    00111100
    00111000
    -8
    9 14 17 22 23 44 63 69 88 94 113 -1
    2
    00
    00
    -4
    0 -1
    0
    Sample Output
    Case 1
    9 14 17 22 23 44 63 69 88 94 113
    Case 2
    00000000
    00000000
    00001111
    00001111
    00011111
    00111111
    00111100
    00111000
    Case 3

    Case 4
    1111
    1111
    1111
    1111
    HINT

    题目大意:事实上就是一种编码的方式,给你图像要求你进行编码,给你编码,让你还原出图像。

    分析:根据题目的说明,编码过程就是将图像分割的过程,全白为0,全黑为1,否则继续分治,最后构造一个叉树进行编码。

    移码的过程就是将10进制的数转化为5进制然后倒过来生成图像。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define  maxlen 3000
      6 using namespace std;
      7 char maps[maxlen][maxlen];
      8 int num[maxlen];
      9 int n,m;
     10 int mypow(int x,int n)
     11 {
     12     int ans=1;
     13     for(int i=0; i<n; ++i)
     14     {
     15         ans*=x;
     16     }
     17     return ans;
     18 }
     19 void Display()
     20 {
     21     for(int i=0; i<n; ++i)
     22     {
     23         for(int j=0; j<n; ++j)
     24         {
     25             cout<<maps[i][j];
     26         }
     27         cout<<endl;
     28     }
     29 }
     30 void Dis()
     31 {
     32     for(int i=0; i<m; ++i)
     33     {
     34         if(i==m-1)
     35             cout<<num[i];
     36         else
     37             cout<<num[i]<<" ";
     38     }
     39     cout<<endl;
     40 }
     41 bool judgew(int x,int y,int s)
     42 {
     43     for(int i=x; i<x+s; ++i)
     44     {
     45         for(int j=y; j<y+s; ++j)
     46         {
     47             if(maps[i][j]!='0')
     48                 return false;
     49         }
     50     }
     51     return true;
     52 }
     53 bool judgeb(int x,int y,int s)
     54 {
     55     for(int i=x; i<x+s; ++i)
     56     {
     57         for(int j=y; j<y+s; ++j)
     58         {
     59             if(maps[i][j]!='1')
     60                 return false;
     61         }
     62     }
     63     return true;
     64 }
     65 void d2g(int x,int y,int d,int s)
     66 {
     67     if(d==0)
     68     {
     69         for(int i=x; i<x+s; ++i)
     70         {
     71             for(int j=y; j<y+s; ++j)
     72                 maps[i][j]='1';
     73         }
     74     }
     75     int k=d%5;
     76     d/=5;
     77     s/=2;
     78     if(k==1)
     79         d2g(x,y,d,s);
     80     else if(k==2)
     81         d2g(x,y+s,d,s);
     82     else if(k==3)
     83         d2g(x+s,y,d,s);
     84     else if(k==4)
     85         d2g(x+s,y+s,d,s);
     86 }
     87 void g2d(int k,int x,int y,int d,int s)
     88 {
     89     int sum=1;
     90     if(judgew(x,y,s))
     91         return ;
     92     if(judgeb(x,y,s))
     93         num[m++]=d;
     94     else
     95     {
     96         sum=mypow(5,k);
     97         s=s/2;
     98         g2d(k+1,x,y,d+sum*1,s);
     99         g2d(k+1,x,y+s,d+sum*2,s);
    100         g2d(k+1,x+s,y,d+sum*3,s);
    101         g2d(k+1,x+s,y+s,d+sum*4,s);
    102     }
    103 }
    104 int main ()
    105 {
    106     int Case=1;
    107     while(scanf("%d",&n)!=EOF)
    108     {
    109         if(n==0)
    110             break;
    111         memset(num,0,sizeof(num));
    112         memset(maps,0,sizeof(maps));
    113         if(n>0)
    114         {
    115             for(int i=0; i<n; ++i)
    116                 for(int j=0; j<n; ++j)
    117                     cin>>maps[i][j];
    118             m=0;
    119             g2d(0,0,0,0,n);
    120             sort(num,num+m);
    121             printf("Case %d
    ",Case++);
    122             Dis();
    123         }
    124         else if(n<0)
    125         {
    126             n=-n;
    127             m=0;
    128             int a;
    129             for(int i=0; i<n; ++i)
    130             {
    131                 for(int j=0; j<n; ++j)
    132                     maps[i][j]='0';
    133             }
    134             while(cin>>a)
    135             {
    136                 if(a==-1)
    137                     break;
    138                 num[m++]=a;
    139                 d2g(0,0,a,n);
    140             }
    141             printf("Case %d
    ",Case++);
    142             Display();
    143         }
    144     }
    145 }
    View Code

    Problem H: Fibonacci数列
    Time Limit: 1 Sec Memory Limit: 128 MB
    Submit: 69 Solved: 20
    [Submit][Status][Web Board]
    Description
    Fibonacci数列的前两项均为1。从第3项起,各项均为其前2项的和,如1, 1, 2, 3, 5, 8, 13, 21, 34, 55,…。给定一个十进制正整数n,计算Fibonacci数列的第n项。
    Input
    输入数据有若干行,每行上有一个正整数n,(0<n<5000)。
    Output
    对于输入中每一个正整数n,直接输出一行结果。
    Sample Input
    2
    15
    25
    Sample Output
    1
    610
    75025
    HINT

    分析:大数高精度,直接使用大数的模板,这个模板很渣。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define  maxlen 5010
     5 using namespace std;
     6 class  bignum
     7 {
     8     private :
     9         int len;
    10         int s[1100];
    11     public:
    12     bignum()
    13     {
    14         memset(s,0,sizeof(s));
    15         len=1;
    16     }
    17     bignum(int num)
    18     {
    19         *this=num;
    20     }
    21     bignum(const char *num)
    22     {
    23         *this=num;
    24     }
    25     bignum operator=(const char *num)
    26     {
    27         len=strlen(num);
    28         for(int i=0;i<len;i++)
    29             s[i]=num[len-i-1]-'0';
    30         return *this;
    31     }
    32     bignum operator=(int num)
    33     {
    34         char s[maxlen];
    35         sprintf (s,"%d",num);// int to char
    36         *this=s;
    37         return *this;
    38     }
    39     string str()const
    40     {
    41         string res="";
    42         for(int i=0;i<len;i++)
    43         res=(char)(s[i]+'0')+res;
    44         if(res=="")
    45         res="0";
    46         return res;
    47     }
    48     bignum operator +(const bignum &b)const
    49     {
    50         bignum c;
    51         c.len=0;
    52         for(int i=0,g=0;g||i<max(len,b.len);i++)
    53         {
    54             int x=g;
    55             if(i<len)
    56                 x+=s[i];
    57             if(i<b.len)
    58                 x+=b.s[i];
    59             c.s[c.len++]=x%10;
    60             g=x/10;
    61         }
    62         return c;
    63     }
    64 };
    65 istream & operator>>(istream &in,bignum & x)
    66 {
    67     string s;
    68     in>>s;
    69     x=s.c_str();
    70     return in;
    71 }
    72 ostream& operator <<(ostream &out,const bignum &x)
    73 {
    74     out<<x.str();
    75     return out;
    76 }
    77 bignum f[maxlen]={1,1,2};
    78 int main ()
    79 {
    80     for(int i=3;i<=5000;++i)
    81         f[i]=f[i-1]+f[i-2];
    82     int n;
    83     int Case=1;
    84     while(scanf("%d",&n)!=EOF)
    85     {
    86         cout<<f[n-1]<<endl;
    87     }
    88 }
    View Code
  • 相关阅读:
    Phpstudy升级到Mysql8
    PHP 匿名函数使用技巧
    PHP 中的CURL 模拟表单的post提交
    Go中局部全局变量的区分
    Php中的goto用法
    struct的匿名用法详解
    Go中多个返回值的技巧
    C# 多线程之List的线程安全问题
    C# 多线程七之Parallel
    C# 多线程六之Task(任务)三之任务工厂
  • 原文地址:https://www.cnblogs.com/shuzy/p/3226621.html
Copyright © 2020-2023  润新知