第四场个人训练赛

https://cn.vjudge.net/contest/168777#overview
25 / 58 A HDU 1008 A
4 / 44 B HDU 1003 AA
24 / 32 C HDU 1994 AAA
4 / 10 D HDU 1998 AAAA
3 / 28 E HDU 1999 AAAAA
15 /31 F HDU 1020 AAAAAA
6 / 11 G HDU 1032 AAAAAAA
0 / 4 H HDU 1143 AAAAAAAA

A(死活都要停留5秒):

The highest building in our city has only one elevator. A request list is made up with N positive numbers. The numbers denote at which floors the elevator will stop, in specified order. It costs 6 seconds to move the elevator up one floor, and 4 seconds to move down one floor. The elevator will stay for 5 seconds at each stop.

For a given request list, you are to compute the total time spent to fulfill the requests on the list. The elevator is on the 0th floor at the beginning and does not have to return to the ground floor when the requests are fulfilled.
Input
There are multiple test cases. Each case contains a positive integer N, followed by N positive numbers. All the numbers in the input are less than 100. A test case with N = 0 denotes the end of input. This test case is not to be processed.
Output
Print the total time on a single line for each test case.
Sample Input
1 2
3 2 3 1
0
Sample Output
17
41

#include<stdio.h>
int main()
{
    int n;
    int s,a;
    int t;
    int i;
    while(scanf("%d",&n)&&n)
    {
        t=0;s=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            if(a>s)
                   t+=6*(a-s);
            else t+=4*(s-a);
            t+=5;
            s=a;
        }
        printf("%d\n",t);
    }    
    return 0; 
}    

B(给出一段数字序列,求出最大连续子段和。典型的动态规划问题,continue···):

Given a sequence a11,a22,a33……ann, your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
Output
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
Sample Input
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
Sample Output
Case 1:
14 1 4(空行)
Case 2:
7 1 6

分析:http://blog.csdn.net/pengwill97/article/details/55139996

#include<stdio.h>
int main()
{
    int i,ca=1,t,s,e,n,x,now,before,max;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d",&n);
       for(i=1;i<=n;i++)
       {
         scanf("%d",&now);
         if(i==1)//初始化 
         {
            max=before=now;//max保留之前算出来的最大和,before存储目前在读入数据前保留的和,now保留读入数据  
            x=s=e=1;//x用来暂时存储before保留的和的起始位置,当before>max时将赋在s位置,s,e保留最大和的start和end位置 
         }
         else {
             if(now>now+before)//如果之前存储的和加上现在的数据比现在的数据小,就把存储的和换成现在的数据,反之就说明数据在递增,可以直接加上 
             {
                before=now;
                x=i;//预存的位置要重置 
             }       
             else before+=now;
              }
         if(before>max)//跟之前算出来的最大和进行比较,如果大于,位置和数据就要重置 
           max=before,s=x,e=i;
       }
       printf("Case %d:\n%d %d %d\n",ca++,max,s,e);
       if(t)printf("\n"); 
    }
    return 0;
}

C:(套公式(逃···

D:(找规律,连续摆数法,continue···)

一个 n 阶方阵的元素是1,2,…,n^2,它的每行,每列和2条对角线上元素的和相等,这样
的方阵叫魔方。n为奇数时我们有1种构造方法,叫做“右上方” ,例如下面给出n=3,5,7时
的魔方.
3
8 1 6
3 5 7
4 9 2
5
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
7
30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20
第1行中间的数总是1,最后1行中间的数是n^2,他的右边是2,从这三个魔方,你可看出“右
上方”是何意。
Input
包含多组数据,首先输入T,表示有T组数据.每组数据1行给出n(3<=n<=19)是奇数。
Output
对于每组数据,输出n阶魔方,每个数占4格,右对齐
Sample Input
2
3
5
Sample Output
8 1 6
3 5 7
4 9 2
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

分析:http://blog.csdn.net/hurmishine/article/details/50825569

规律:从第一行中间一个数开始更新,如果是当前位置在第一行(但不是最后一列),下一个位置是 下一列最后一行;如果当前位置是最后一列(但不是第一行),下一个位置是 上一行第一列;如果不是最后一列并且右上角的值没有更新,下一个位置就是右上角;如果右上角的值已经更新,下一个位置是下一行同一列位置;如果当前位置在最右上角,下一个位置是同列下一行位置;ps规律来自于http://blog.csdn.net/lyhvoyage/article/details/9051019

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string.h>

int flag[100][100],m[100][100];//标记数组和魔法数组
int main()
{
    int n,i,j,x,a,b;
    while(~scanf("%d",&n))
    {
        memset(flag,0,sizeof(flag));
        memset(m,0,sizeof(m));
        if(n%2==0||n==1);//当n为偶数和1时不做处理
        else
        {
            for(x=1;x<=n*n;x++)//判断x的位置
            {
                if(x-1)
                {
                    a=i-1;
                    b=j+1;
                    if(a<1)
                        a=n;
                    if(b>n)
                        b=1;
                    if(flag[a][b]==0)
                        i=a,j=b;
                    else
                        i++;
                    m[i][j]=x;
                    flag[i][j]=1;
                }
                else
                {
                    j=n/2+1;
                    i=1;
                    m[i][j]=x;
                    flag[i][j]=1;
                }
            }
            for(i=1;i<=n;i++)//输出魔方
            {
                for(j=1;j<=n;j++)
                printf("%4d",m[i][j]);
                putchar('\n');
            }
        }
    }
    return 0;
}

E:(打表?continue···)

s(n)是正整数n的真因子之和,即小于n且整除n的因子和.例如s(12)=1+2+3+4+6=16.如果任何
数m,s(m)都不等于n,则称n为不可摸数.
Input
包含多组数据,首先输入T,表示有T组数据.每组数据1行给出n(2<=n<=1000)是整数。
Output
如果n是不可摸数,输出yes,否则输出no
Sample Input
3
2
5
8
Sample Output
yes
yes
no

分析:

(摘录)
题目只是求1000以内的不可摸数。
我们可以想想一个数的s(n)大约等于多少,因为s(素数)=1,所以我们不需要考虑素数。
如果一个数n是一个素数m的平方,那么其s(n)会是最小的,s(n)=m+1
1000内最大的素数是997,其平方是994009,也就说s(994009)=997+1=998
这个994009就是我们需要打表的最大范围(我近似看成100W),
也就是说如果一个数大于100W,那个s(n)必定大于1000,我们不需要考虑。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int funs(int a) {
    int res = 1;
    int i;
    int oa =(int)sqrt((double)a);
    for(i=2; i<=oa; i++) {
        if(a%i==0) {
            res+=i;
            if(i*i!=a)
                res+=a/i;
        }
    }
    return res;

}
int issu(int a) {
    int i;
    int oa =(int)sqrt((double)a);
    for(i=2; i<=oa; i++) {
        if(a%i==0) {
            return 0;
        }
    }
    return 1;
}
int main() {
    int i,n,num;
    int ta[1001];
    int temp;
    for(i=0; i<1001; i++)
        ta[i] = 0;
    //第一次打表
    for(i=2; i<27500; i++) {
        temp = funs(i);
        if(temp<1010&&temp>=1)
            ta[temp] = 1;
    }
    //第二次打表
    for(i=3; i<1001; i++) {
        if(issu(i-1) && ta[i]==0)
            ta[i] = 1;
    }

    scanf("%d",&n);
    while(n--) {
        scanf("%d",&num);
        if(ta[num])
            printf("no\n");
        else
            printf("yes\n");
    }
    return 0;
}

F:(字符串)

Given a string containing only ‘A’ - ‘Z’, we could encode it using the following method: 1. Each sub-string containing k same characters should be encoded to “kX” where “X” is the only character in this sub-string.
2. If the length of the sub-string is 1, ‘1’ should be ignored.
Input
The first line contains an integer N (1 <= N <= 100) which indicates the number of test cases. The next N lines contain N strings. Each string consists of only ‘A’ - ‘Z’ and the length is less than 10000.
Output
For each test case, output the encoded string in a line.
Sample Input
2
ABC
ABBCCC
Sample Output
ABC
A2B3C

#include<string.h>
#include<stdio.h>
int main ()
{
  int t,cnt;
  char str[10010];
 while( scanf("%d",&t) != EOF )
 {
  while(t--)
  {

      scanf("%s",str);
      int len=strlen(str);
      for( int i = 0 ;i < len ;i++)
      {
          cnt = 1 ;                                                                                                          
          for( int j=i+1; j < len;j++) /*双循环用于周期性探测*/
             if( str[i] == str[j] )
                 cnt++;
             else 
                 break;

          if(cnt>1)
            printf("%d%c",cnt,str[i]);
          else
            printf("%c",str[i]);

          i+=(cnt-1); /*i探测时跳跃式的,跳过已经重复过的*/
      }
      printf("\n");
  }
 }
  return 0;
}

G:https://cn.vjudge.net/contest/168777#problem/G(有坑,continue···)

#include <stdio.h>
int stepCount(int n)
{
    int count = 0;
    while(n != 1)
    {
        if(n % 2)
        {
            n = 3*n+1;
        }
        else
        {
            n /= 2;
        }
        count++;
    }
    return ++count;
}
int main()
{
    int i, j, n, temp, count, ii, jj, k;
    while(scanf("%d%d", &i, &j)!= EOF)
    {
        temp = 0;
        ii = i, jj = j;
        if(i > j) k = ii, ii = jj, jj = k;
        for(n = ii; n <= jj; n++)
        {
            count = stepCount(n);
            if(temp < count) temp = count;
        }
        printf("%d %d %d\n", i, j, temp);
    }
}
(摘录)我们可以发现,11的循环长度是1534的循环长度是14,一次类推;也就是说,当我们计算22的循环长度时,上述值的循环长度就不用再次计算。那么我们就可以在计算一个值的循环长度时,将其产生的序列中值的循环长度都保存起来,下次需要时直接调用就好!这种思想在很多地方都有应用!具体细节见我的代码。
-------------------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int I, J;
vector<int> record;
vector<int> cycle;
int Cycle(int n)
{
    while (n != 1)
    {
        if (n <= J && record[n]) 
        return record[n]; //当n值的循环长度已经计算过,那么序列中在它后面的值一定也已经计算过,直接返回
        cycle.push_back(n); //否则的话将当前值保存,用于作备忘录
        if (n & 1) n = 3 * n + 1;
        else n /= 2;
    }
    cycle.push_back(1);
    return 0;
}
int main()
{   
    int maxLen;
    int input_I, input_J;
    while (cin >> I >> J)
    {
        input_I = I, input_J = J;
        if (I > J) swap(I, J);
        record.assign(J + 1, 0);
        maxLen = 0;
        for (int k = I; k <= J; k++)
        {
            cycle.clear();
            int m = Cycle(k);
                        //对系列中每个值的循环长度作备忘录
            for (int i = 0; i < cycle.size(); i++)
            {
                if (cycle[i] <= J)
                    record[cycle[i]] = m + cycle.size()-i;
            }
            maxLen = max(maxLen, record[k]);
        }
        cout << input_I << " " << input_J << " " << maxLen << endl;
    }

    return 0;
}
#include <stdio.h>
int ttt(int n)
{
    int count=0;
    while(n!=1)
    {
        if(n%2==0)
            n/=2;
        else
            n=n*3+1;
        count++;
    }
    return count+1;
}

int main()
{
    int i,j,max,t;
    while(~scanf("%d%d",&i,&j))
    {
        printf("%d %d ",i,j);
        if(i>j) t=i,i=j,j=t;
        max=ttt(i);
        for(i++;i<=j;i++)
        {
            if(max<ttt(i))
                max=ttt(i);
        }
        printf("%d\n",max);
    }
    return 0;
}

#include <stdio.h>
#include <algorithm>

using namespace std;

int fun(int n)
{
    int count = 1;
    while(n != 1)
    {
        if(n%2 == 0) //even
        {
            n = n/2;
        }
        else   //odd 
        {
            n = n*3+1;
        }
        count++;

    }   
    return count;
}



int main()
{
    int n,m,i,count,begin,end;
    int max;
    while(scanf("%d %d",&n,&m) != EOF)
    {
        max = 1;
        begin = n;
        end = m;
        if(n > m)  //note:m may less than n
        {
            swap(begin,end);
        }
        for(i=begin;i<=end;i++)
        {
            count = fun(i); 
            if(count > max)
            {
                max = count;
            }
        }

        printf("%d %d %d\n", n,m,max);
    }

    return 0;
}

H:(dp?数学推导?递归?continue···)

In how many ways can you tile a 3xn rectangle with 2x1 dominoes? Here is a sample tiling of a 3x12 rectangle. (有图)
这里写图片描述
Input
Input consists of several test cases followed by a line containing -1. Each test case is a line containing an integer 0 ≤ n ≤ 30.
Output
For each test case, output one integer number giving the number of possible tilings.
Sample Input
2
8
12
-1
Sample Output
3
153
2131

http://www.cppblog.com/menjitianya/archive/2015/10/23/212084.html
例题1有详解,非常细致,博客是 英雄哪里出来 写的

顺便附上按照这个思路码的ac代码
#include<cstdio>
#include<cstring>
const int MAXN=30+5;
int dp[MAXN][3];
int main()
{
    dp[0][0]=dp[0][2]=1;
    dp[1][1]=1;
    for(int i=2;i<MAXN;++i)
    {
        dp[i][0]=dp[i-1][1]+dp[i-2][2]+dp[i-2][0];
        dp[i][1]=dp[i-1][2];
        dp[i][2]=dp[i][0]+dp[i-1][1];
    }
    int n;
    while(~scanf("%d",&n))
    {
        if(n==-1) break;
        printf("%d\n",dp[n][0]);
    }
}
#include<iostream>//当n为奇数时,面积也是奇数,所以不可能用偶数的面积填满,即n为奇数时输出为0
#include<cstring>//当n为偶数时仔细观察会发现
/*可以看到图形的高都是3,所以要么在最上面放一层
或者在最下面放一层,让高变成2,而让图不可分
剩下的高为2的部分,必须在两头各竖着放一个
要不图形就可以分成两个小图形了
这样就不满足我们递推的思路了
这样其实可以得到一个规律,只有k为2时g(k)是3
其余的情况,g(k)都是2
这样我们就可以简单的写出递推式:
f(n)=3*f(n-2)+2*f(n-4)+.....+2*f(2)
同理f(n-2)=3*f(n-4)+2*f(n-6)+.....+2*f(2)
f(n)-4*f(n-2)=-f(n-4);所以最终的递推式就是f(n)=4*f(n-2)-f(n-4)
*/
#include<string>
#include<cstdio>
#include<algorithm>
const int MAX=31;
int s[MAX];
using namespace std;
int main()
{
    int i,n;
    s[0]=1;
    s[2]=3;
    for(i=4;i<MAX;i+=2)
    {
        s[i]=4*s[i-2]-s[i-4];
    }
    while(cin>>n,n>=0)
    {
        if(n&1)
        cout<<0<<endl;
        else
        cout<<s[n]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值