[BestCoder #33]简要题解

真是伤心。。。这场比赛我两个题在20min中全部做完,全部因为忘了特判导致fst,我是sb。。。

A.zhx’s submissions

http://acm.hdu.edu.cn/showproblem.php?pid=5186
最水的题,纯比手速,结果我为了抢时间忘记特判,最后fst掉了。。。
要特判的情况就是输出的答案为0的情况。。。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 500

using namespace std;

char s[MAXN];
int ans[MAXN],ss[MAXN];

int main()
{
    int n,B;
    while(scanf("%d%d",&n,&B)!=EOF)
    {
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            int len=strlen(s+1);
            for(int i=1;i<=len;i++)
            {
                if(s[len-i+1]>='0'&&s[len-i+1]<='9')
                    ss[i]=s[len-i+1]-'0';
                else
                    ss[i]=s[len-i+1]-'a'+10;
            }
            for(int i=1;i<=len;i++)
                ans[i]=(ans[i]+ss[i])%B;
        }
        int tmp=MAXN-1;
        while(!ans[tmp]&&tmp>=1) tmp--;
        if(!tmp) printf("0"); //坑爆了!!!
        for(int i=tmp;i>=1;i--)
        {
            if(ans[i]<=9) printf("%d",ans[i]);
            else printf("%c",ans[i]-10+'a');
        }
        printf("\n");
    }
    return 0;
}

B.zhx and contest

还是特判, n>1 时最终答案为 2n2 n=1 时显然答案为1。。。
但是仅仅这些还不够,由于题目中所有数的范围在1e18范围内,做乘法时可能爆long long,因此要用快速加,然后如果 n=1,p=1 时答案为0,显然 n=1 时只输出 1 是错的,要输出1 mod p

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

using namespace std;

typedef long long int LL;

LL mul(LL a,LL b,LL p)
{
    LL ans=0;
    while(b)
    {
        if(b&1) ans=(ans+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return ans;
}

LL fastPow(LL base,LL pow,LL p)
{
    LL ans=1;
    while(pow)
    {
        if(pow&1) ans=mul(ans,base,p);
        base=mul(base,base,p);
        pow>>=1;
    }
    return ans;
}

int main()
{
    LL n,p;
    while(scanf("%I64d%I64d",&n,&p)!=EOF)
    {
        if(n==1)
        {
            printf("%I64d\n",1%p);
            continue;
        }
        LL ans=fastPow(2,n,p);
        ans=(ans-2+p)%p;
        printf("%I64d\n",ans);
    }
    return 0;
}

C.zhx and contest

标准做法是DP。。。不是很好想。。。。
这里我用的做法是参考别人的一种非常巧妙的二分+深搜。我们可以先按照每个题目最早可以开始做的时刻( liti )升序排序,显然所有题目权值之和 <w 则无解。而且显然最少做完所有题目的时间是可以二分出来的,因此我们二分最终需要的最少时间,从最后一个题往前倒着搜,爆枚每个题是否选择做了(如果这个题最早可以做出来的时间在当前时刻之前,而且当前的时刻足够这个题做出来的话,这个题就可以选择做,否则一定不能做),这样的方法比较简单,而且正确性比较显然。
当然,这样的爆搜有很多可以剪枝的地方,我们可以预处理出排序后的题目权值的前缀和,如果在搜索过程中发现,如果1~当前题都做出来,仍然做不到w分,那么说明当前的DFS状态显然是无解的,直接退出。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 100

using namespace std;

typedef long long int LL;

struct Prob
{
    int t,l;
    LL v;
}probs[MAXN];

LL sum[MAXN];

int n,w;

bool cmp(Prob a,Prob b)
{
    return a.l-a.t<b.l-b.t; //!!!!!!!!
}

bool DFS(int x,int t,LL solved) //zuo le x ti,shi jian yong le time,zuo chu le solved fen
{
    if(solved>=w) return true;
    if(x<=1) return false;
    if(solved+sum[x-1]<w) return false;
    if(probs[x-1].t<=t&&probs[x-1].l<=t)
        if(DFS(x-1,t-probs[x-1].t,solved+probs[x-1].v))
            return true;
    if(DFS(x-1,t,solved))
        return true;
    return false;
}

int main()
{
    while(scanf("%d%d",&n,&w)!=EOF)
    {
        //memset(used,false,sizeof(used));
        for(int i=1;i<=n;i++)
            scanf("%d%lld%d",&probs[i].t,&probs[i].v,&probs[i].l);
        sort(probs+1,probs+n+1,cmp);
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+probs[i].v;
        int lowerBound=0,upperBound=1000000000,ans;
        if(sum[n]<w)
        {
            printf("zhx is naive!\n");
            continue;
        }
        while(lowerBound<=upperBound)
        {
            int mid=(lowerBound+upperBound)>>1;
            if(DFS(n+1,mid,0))
            {
                upperBound=mid-1;
                ans=mid;
            }
            else lowerBound=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:([BestCoder #33]简要题解)