Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

2013腾讯编程马拉松初赛第一场(3月21日) 解题报告

$
0
0

A题 (hdu 4505)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4505

解题思路:    一次遍历就可以,这道题可以推出公式 max*10+(k*5)+n

                   max最高楼层,k多少个楼层需要开门,n一共多少个人

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 400
int a[MAX];
int main()
{
    int t,n,i,j,m,k,max;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(a,0,sizeof(a));
        for(i=0,k=0,max=0;i<n;i++)
        {
            scanf("%d",&m);
            if(a[m]==0)
                k++;
            a[m]++;
            if(m>max)
                max=m;
        }
        printf("%d\n",max*10+(k*5)+n);
    }
    return 0;
}


B题 (hdu 4506)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4506

解题思路:    一个个求多少次方速度很慢,可以用快速幂

代码:

#include<stdio.h>
__int64 a[10005];
__int64 get_mi(__int64 a,__int64 b,int n)
{
    if(0 == a) return 0;
    if(0 == b)  return 1;
    __int64 r=1;
    while(b)
    {
        if(b&1)
            r=(r*a)%n;
        a=(a*a)%n;
        b>>=1;
    }
    return r;
}
int main()
{
    int T,i,y;
    __int64 n,t,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d",&n,&t,&k);
        for(i=0;i<n;i++)
        {
            scanf("%I64d",&a[i]);
        }
        __int64 x;
        int mmm=1000000007;
        __int64 sum;
        sum=get_mi(k,t,mmm);
        t%=n;
        for(i=0;i<n-1;i++)
        {
            if(i<t)
                y=i+n-t;
            else
                y=i-t;
            x=(a[y]*sum)%mmm;
            printf("%I64d ",x);
        }
        if(i<t)        y=i+n-t;
        else y=i-t;
        x=(a[y]*sum)%mmm;
        printf("%I64d\n",x);
    }
    return 0;
}

D题 (hdu 4508)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4508

解题思路:    0-1背包的模版题,不一定要把背包装满

代码:

#include <stdio.h>
#include <string.h>
#define MAX_N 100001
#define MAX_V 100001
#define _MAX -0x3f3f3f3f
int n,m,f[MAX_V],c[MAX_N],w[MAX_N];
int DP(int full)
{
    int i,v;
    if(full) //如果是恰好放满,则除f[0][0]外都初始化为无穷小
    {
        memset(f,_MAX,sizeof(f));
        f[0]=0;
    }
    else  memset(f,0,sizeof(f)); //如果不一定要放满,则初始化为0
    for(i=1;i<=n;i++)
    {
        for(v=c[i];v<=m;v++)
        {
            f[v]=(f[v-c[i]]+w[i]>f[v])?f[v-c[i]]+w[i]:f[v];  // ****状态转移方程****
        }
    }
    return f[m];
}
int main ()
{
    int i;
    while(scanf("%d",&n)!=EOF)
    {
       for(i=1;i<=n;i++)
       {
            scanf("%d%d",&w[i],&c[i]);
       }
         scanf("%d",&m);
        printf("%d\n",DP(0)); //0为非满,1非恰好满
    }
    return 0;
}

E题(hdu 4509)

题目链接:    http://acm.hdu.edu.cn/showproblem.php?pid=4509

解题思路:    开始没有考虑到时间会有交叉的情况,WA了两次

                   把分钟转换成数字,那么24小时就有24*60=1440

                   构建数组a[1440],初始化为-1

                   每行给出的两个时间都可以转换成一个区间存不存在

                   如 01:00 02:00,转换成a[60]到a[120]所有的元素都为0

                   这道题可以用线段数优化,但是数组不大,效果不那么明显

                   可以用memset代替for,效率高一点

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 2000
int time[MAX];
int main()
{
    int n,i,t,a,b,c,d,s,k;
    while(scanf("%d",&n)!=EOF)
    {
        memset(time,-1,sizeof(time));  //-1代表空闲
        for(i=0;i<n;i++)
        {
            scanf("%d:%d %d:%d",&a,&b,&c,&d);
            s=a*60+b;
            t=c*60+d;
            memset(time+s,0,(t-s)*sizeof(time[0]));  //memset代替for循环
        }                                            //0代表忙碌
        for(i=0,k=0;i<1440;i++)
            if(time[i]==-1)
                k++;
        printf("%d\n",k);
    }
    return 0;
}


作者:qq7366020 发表于2013-3-22 0:52:05 原文链接
阅读:85 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>