问题 - 来自利沃夫动物园的一只小象非常喜欢幸运数字。每个人都知道幸运数字是正整数,其十进制表示仅包含幸运数字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。
4 == L[i]
应该位于if块7 > L[i]
之前。现在代码工作正常。
答案 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])