Codechef Q - 为什么我收到“错误答案”错误

时间:2012-06-11 04:39:57

标签: c++ algorithm

问题 - 来自利沃夫动物园的一只小象非常喜欢幸运数字。每个人都知道幸运数字是正整数,其十进制表示仅包含幸运数字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。换句话说,他想知道价值 max {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()

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

变量 flagL flagR 告诉您是否需要分别检查L和R.

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

现在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

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

所以我们现在有两个选择,4和L [0] +1(这是递归的地方)

为什么L [0] +1?因为如果我们在ans [0]中放置L [0] +1,则ans [0]将落在L [0]和R [0]之间(对于此R [0] - L [0]> = 2)无论我们在剩下的数字中放置什么,ans []永远不会超出范围。但是我们还必须检查ans [0]是4.在最后一个例子中,它没有帮助,但是如果R是&gt; = 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]&lt; R [0],因此 ans 将始终&lt;的 - [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]之前。现在代码工作正常。

1 个答案:

答案 0 :(得分: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])