1

问题- 来自利沃夫动物园的小象非常喜欢幸运数字。大家都知道幸运数字是正整数,其十进制表示只包含幸运数字4和7。例如数字47、744、4是幸运数字,而5、17、467则不是。

令 F4(X) 为 X 的十进制表示的位数 4,F7(X) 为 X 的十进制表示的位数 7。例如,F4(456) = 1, F4(444) = 3, F7(1) = 0, F7(747) = 2。小象想知道最大的乘积 F4(X) ∙ F7(X),其中 L ≤ X ≤ R。换句话说,他想知道最大值{F4(X) ∙ F7(X) : L ≤ X ≤ R}。

1 <= L <= R <= 10 18

示例:1) 对于范围,1 100答案将是 1 {47,74}

2) 4199 6000 答案将是 4 {4747, 4477}

我觉得我的代码是正确的,但是在提交它时得到了错误的答案。谁能帮我找出到底出了什么问题?

我的算法不会错(它非常简单)。我已经仔细检查了实现(它处理了所有可能的情况)。很难相信某些输入会出错。

这是 C++ 代码:

#include <cstdio>
#include <cstring>
using namespace std;
char buf1[20],buf2[20];
int *L, *R, *ans, len, ansn;
bool flagL, flagR;

inline int count(int n)
{
    int a=0,c=0;
    for(;a<len;a++) if(ans[a] == n) c++;
    return c;
}
inline int max(int a, int b) { return a>b ? a:b; }
inline int min(int a, int b) { return a<b ? a:b; }

inline void f(int i, int n)
{
    int a=0,n4=0,n7=0,t;
    for(;a<=i;a++) if(ans[a] == 4) n4++; else if(ans[a] == 7) n7++;
    while(n)
    {
        if(n4 == n7)
        {
            n4 += n/2;
            n7 += (n-n/2);
            break;
        }
        else if(n4 > n7)
        {
            t = min(n,n4-n7);
            n -= t;
            n7 += t;
        }
        else if(n7 > n4)
        {
            t = min(n,n7-n4);
            n -= t;
            n4 += t;
        }
    }
    ansn = max(ansn,n4*n7);
}

void solve(int i, bool flagL, bool flagR)
{
    while(i<len)
    {
        if(flagL && !flagR)
        {
            if(4 > L[i])
            {
                f(i-1,len-i);
                return;
            }
                    if(4 == L[i])
            {
                ans[i] = 4;
                solve(i+1, 1, 0);
                ans[i] = 7;
                f(i,len-i-1);
                return;
            }
            if(7 > L[i])
            {
                ans[i] = 7;
                f(i,len-i-1);
                return;
            }
            if(7 == L[i])
            {
                ans[i] = 8;
                f(i,len-i-1);
                ans[i] = 7;
                i++;
                continue;
            }
            // else
                ans[i] = 9;
                if(ans[i] > L[i])
                {
                    f(i,len-i-1);
                    return;
                }
                else
                {
                    i++;
                    continue;
                }
        }
        if(!flagL && flagR)
        {
            if(7 < R[i])
            {
                f(i-1,len-i);
                return;
            }
            if(7 == R[i])
            {
                ans[i] = 4;
                f(i,len-i-1);
                ans[i] = 7;
                i++;
                continue;
            }
            if(4 < R[i])
            {
                ans[i] = 4;
                f(i,len-i-1);
                return;
            }
            if(4 == R[i])
            {
                ans[i] = 3;
                f(i,len-i-1);
                ans[i] = 4;
                i++;
                continue;
            }
            // else
                ans[i] = 0;
                if(ans[i] < R[i])
                {
                    f(i,len-i-1);
                    return;
                }
                else
                {
                    i++;
                    continue;
                }
        }
        if(flagL && flagR)
        {
            if(R[i] - L[i] == 1)
            {
                ans[i] = L[i];
                solve(i+1,1,0);
                ans[i]++;
                solve(i+1,0,1);
                return;
            }
            bool four = 4 > L[i] && 4 < R[i];
            bool sev = 7 > L[i] && 7 < R[i];
            if (four && sev)
            {
                f(i-1,len-i);
                return;
            }
            else if (four && !sev)
            {
                ans[i] = 4;
                f(i,len-i-1);
            }
            else if (!four && sev)
            {
                ans[i] = 7;
                f(i,len-i-1);
            }
            if (L[i] == 4 || L[i] == 7 || R[i] == 4 || R[i] == 7)
            {
                if(L[i] == R[i]) { ans[i] = L[i]; i++; continue; }

                if(L[i] == 4 && R[i] == 7)
                {
                    ans[i] = 4;
                    solve(i+1,1,0);
                    ans[i] = 7;
                    solve(i+1,0,1);
                    ans[i] = 5;
                    f(i,len-i-1);
                    return;
                }
                if(R[i] - L[i] >= 2)
                {
                    ans[i] = L[i]+1;
                    f(i,len-i-1);

                    if(L[i] == 4 || L[i] == 7)
                    {
                        ans[i] = L[i];
                        solve(i+1,1,0);
                    }
                    if(R[i] == 4 || R[i] == 7)
                    {
                        ans[i] = R[i];
                        solve(i+1,0,1);
                    }
                    return;
                }
            }
            else
            {
                if (R[i] - L[i] >= 2)
                {
                    ans[i] = L[i]+1;
                    f(i,len-i-1);
                    return;
                }
                ans[i] = L[i];
            }
        }
        i++;
    } // end of while
    ansn = max(ansn, count(4)*count(7));
}

int main()
{
    int a,t; scanf("%d\n",&t);
    while(t--) // test cases
    {
        scanf("%s %s",&buf1,&buf2);
        len = strlen(buf2);
        L = new int[len];
        R = new int[len];
        ans = new int[len];
        for(a=0;a<len;a++) R[a] = buf2[a]-48;
        for(a=0;a<len-strlen(buf1);a++) L[a] = 0;
        int b=a;
        for(;a<len;a++) L[a] = buf1[a-b]-48;
        flagL = flagR = 1; ansn = 0;
        solve(0,1,1);
        printf("%d\n",ansn);
    }
    return 0;
}

算法:

首先,将 L,R 的数字放入长度 = no 的数组 L[],R[] 中。R 中的数字。并初始化一个数组 ans[] 以跟踪答案整数(F4(ans)*F7(ans) 最大的整数)。

在左侧将 L 填充 0,使其长度等于 R。(所以 1,100 变为 001,100)这是在 main() 本身中完成的,然后调用solve()

真正的逻辑:运行一个循环,for i in range(0,len(R)) 对于每个 i,比较 L[i] 和 R[i]

变量flagLflagR告诉你是否需要分别检查 L 和 R。

假设 L[], R[] 最初是:238 967 首先我们需要从第 0 个索引开始检查它们(因此 solve(0,1,1) 或 solve(0,true,true) )。

现在 4 和 7 都落在L [0] 和 R[0] 之间。因此,{4,7} 的任何排列都可以放在 3 位数字中,而 ans[] 不会超出范围[L,R]。所以答案是2。

如果范围是:238 和 545

只有 4 会落在2 和 5之间,所以我们将 4 放在 ans[0] 中,并且 {4,7} 的任何排列都可以放在其余位置。所以答案又是2。

如果范围是:238 和 410

4 和 7 都不在 L[0] 和 R[0] 之间。但请注意,R[0] 为 4。

所以我们现在有 2 个选择,4 和 L[0]+1(这就是递归的用武之地)

为什么 L[0]+1 ?因为如果我们将 L[0]+1 放在 ans[0] 中,ans[0] 将落在 L[0] 和 R[0] 之间(对于这个 R[0] - L[0] >= 2)并且无论我们在剩余的数字中输入什么,ans[] 都不会超出范围。但是我们还必须检查 ans[0] 是否为 4。在最后一个示例中,它不会有帮助,但如果 R​​ >= 477,它就会有帮助。

所以答案是 1。(如果 R >= 477,则为 2)

让我们讨论另一个例子:

范围:4500 5700

因为 R[0] 和 L[0] 仅相差 1,我们必须检查两者,一次是 ans[i] = L[i],然后是 ans[i] = R[i](或 ans[i ]++)

现在,如果我们检查 ans[i] = 4,我们将不必再比较 ans[i] 和 R[i],因为 ans[0] < R[0],因此ans始终 < R。所以我们像这样递归调用solve():solve(i+1, true, false)

下一次,当 ans[0] = R[0] 时,我们就不必将 ans 与 L 进行比较(因为 ans > L,我们在剩下的 2 个地方放什么)。然后我们像这样调用solve():solve(i+1, false, true)。

您会了解它是如何工作的,而且,如果您查看我的代码,则不会遗漏任何可能的测试用例。我不知道我为什么要获得 WA。


PS:安德鲁指出了错误。条件顺序错误。if 块4 == L[i]应该在 if 块之前7 > L[i]。现在代码可以正常工作了。

4

1 回答 1

4
        if(7 > L[i]) // 7 > 4 ?
        {
            ans[i] = 7;
            f(i,len-i-1);
            return;
        }
        if(4 == L[i])  // how is this ever reachable?
        {
            ans[i] = 4;
            solve(i+1, 1, 0);
            ans[i] = 7;
            f(i,len-i-1);
            return;
        }

我想你的意思是:

-            if(7 > L[i])
+            if(7 < L[i])
于 2012-06-11T05:29:25.290 回答