hdu4574Bombs(枚举+dfs)

来源:互联网 发布:崩坏3矩阵探索buff最新 编辑:程序博客网 时间:2024/05/22 03:07

题目请戳这里

题目大意:给一个区间[A,B],表示有B - A + 1种火药,火药i的威力值为i,现在要用这些火药做炸弹,每次按原料的字典序做炸弹。每个炸弹的威力值是每种原料威力值的乘积。现在给一个区间[L,R]表示炸弹的威力值范围,求第K个炸弹的配方。

题目分析:因为炸弹的威力值是原料威力值的乘积,R不超过10^9,A至少为2,所以极端情况下炸弹至少要30种原料,所以直接搜就可以了。

首先根据给定的2个区间,求出重合的区间,表示只用一种原料能做的炸弹有多少,如果K满足这个范围,直接输出答案。

然后根据[L,R]区间确定所要原料的数量的上下界。然后枚举原料长度,dfs。

主要的剪枝是,当搜到第i中火药的时候,假设剩下的全部用威力值最大的B种火药,如果还不能达到炸弹威力值下界L,退出;假设剩下的全部用威力值最小的A种火药,已经超过炸弹威力值上界R,退出。

不过我加了这个剪枝还是TLE,后来又加了个小剪枝,就是搜到倒数第二层的时候,最后一层的情况直接统计,不用去搜最后一层了。

详情请见代码:

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 ll;ll A,B,L,R,K;ll path[400];bool flag;ll pow(ll a,ll b){    ll ret = a;    for(int i = 1;i < b;i ++)        ret *= a;    return ret;}void dfs(ll cur,int deep,int dp,ll po){    if(flag)        return;    path[dp] = cur;    if(dp + 1 == deep)//倒数第二层    {        ll ta = L/po;        if(L%po)            ta ++;        ll tb = R/po;        ll tmp;        if(tb < cur)            tmp = 0;        else        {            if(tb <= B)            {                if(ta < cur)                    tmp = tb - cur + 1;                else                    tmp = tb - ta + 1;            }            else            {                if(ta < cur)                    tmp = B - cur + 1;                else if(ta <= B)                        tmp = B - ta + 1;                    else                        tmp = 0;            }        }        K -= tmp;        if(K > 0)            return;        else            K += tmp;    }    ll i;    if(dp == deep)    {        if(po >= L && po <= R)            K --;        if(K == 0)        {            printf("%I64d\n",po);            for(i = 1;i < dp;i ++)                printf("%I64d ",path[i]);            printf("%I64d\n",path[i]);            flag = true;        }        return;    }    i = L/po;    i = i / (pow(B,(deep - dp - 1)));    if(i < cur)        i = cur;    for(;i <= B;i ++)    {        if(pow(i,(deep - dp)) * po > R)            return;        dfs(i,deep,dp + 1,po * i);    }}int main(){    int t,cas = 0;    ll i,j;    scanf("%d",&t);    while(t --)    {        scanf("%I64d%I64d%I64d%I64d%I64d",&A,&B,&L,&R,&K);        printf("Case #%d: ",++cas);        int cros = 0;        if(R < A)        {            printf("-1\n");            continue;        }        ll tans;        if(R <= B)        {            if(L < A)            {                cros = R - A + 1;                if(cros >= K)                    tans = A + K - 1;            }            else            {                cros = R - L + 1;                if(cros >= K)                    tans = L + K - 1;            }        }        else        {            if(L < A)            {                cros = B - A + 1;                if(cros >= K)                    tans = A + K - 1;            }            else if(L >= A && L <= B)                 {                     cros = B - L + 1;                     if(cros >= K)                        tans = L + K - 1;                 }                else                    cros = 0;        }        if(cros >= K)        {            printf("%I64d\n%I64d\n",tans,tans);            continue;        }        K -= cros;        ll l,r;        l = r = 2;        ll ta,tb;        ta = A;        tb = B;        while((ta*A) < R)        {            r ++;            ta = ta * A;        }        while((B*tb) < L)        {            l ++;            tb = tb * B;        }        flag = false;        for(i = l;i <= r && !flag;i ++)        {            j = L / (pow(B,i - 1));            if(j < A)                j = A;            for(;j <= B && !flag;j ++)            {                if(pow(j,i) > R)                    break;                dfs(j,i,1,j);            }        }        if(!flag)            printf("-1\n");    }    return 0;}/*1002 2 1 4 12 5 1 4 473 23642 12 20903 294012 50 1 1000000000 8151802 1000000 2 1000000000 10000002 100000 2 1000000000 10000002 10000 2 1000000000 10000002 1000 2 1000000000 10000002 100 2 1000000000 10000002 100000 1000000 1000000000 1000000*//*ans:2242 2-1592004 4 5 20 3742 261611 56510151101 5051273 3 36797287 17 68 84304624631 98266*/


原创粉丝点击