2的有趣功能-算法/数学(来自Hackerrank ACM APC)
我在最近的一次比赛中遇到了一个问题。 我无法找到解决方案,目前还没有关于这个问题的社论 我在这里引用问题陈述,以防链接不起作用2的有趣功能-算法/数学(来自Hackerrank ACM APC),c,algorithm,math,C,Algorithm,Math,我在最近的一次比赛中遇到了一个问题。 我无法找到解决方案,目前还没有关于这个问题的社论 我在这里引用问题陈述,以防链接不起作用 查找大于或等于A且小于或等于B的整数n的数量(A编程竞赛中经常发生的情况我提出了一个启发式方法,我没有证明,但似乎是合理的。我编写了一个简短的程序来查找最大1000000的数字,它们是: 36 736 8736 48736 948736 因此,我的理论是:每个连续数字都有前一个数字的后缀,只增加一个数字。希望这能让你找到正确的解决方法。请注意,如果我的假设是正确的,
查找大于或等于A且小于或等于B的整数n的数量(A编程竞赛中经常发生的情况我提出了一个启发式方法,我没有证明,但似乎是合理的。我编写了一个简短的程序来查找最大1000000的数字,它们是:
36
736
8736
48736
948736
因此,我的理论是:每个连续数字都有前一个数字的后缀,只增加一个数字。希望这能让你找到正确的解决方法。请注意,如果我的假设是正确的,你只需要查找150个数字,而查找每个连续数字需要检查可能添加的9个数字
对于类似问题的一般建议-总是尝试找到前几个数字,并思考一些关系
在一场比赛中,经常会出现这样的情况:你提出了一个类似于我上面提出的理论,但没有时间证明它。你没有时间证明它。只希望你是对的,并编写代码
编辑:我相信我能够证明我的上述猜测(事实上,我遗漏了一些数字——见文章末尾)。首先让我指出,v3ga在评论中指出,上述算法一直工作到75353432948736
,因为没有任何数字可以让新数字变得“有趣”根据你给出的定义。然而,我完全错过了另一个选项-你可以预先添加一些数字0,然后添加一个非零数字
现在我将证明一个引理:
引理:如果a1a2…an是一个有趣的数字,n大于3,那么a2…an也是有趣的
证明:
2a1a2…an=2a1*10n-1*2a2a2…an
现在我将证明2a1*10n-1*2a2a2…an与2a2a2…模10n-1相当
为此,让我们证明2a1*10n-1*2a2a2…an-2a2a2…an可被10n-1整除
2a1*10n-1*2a2a2…an-2a2a2…an=
2A2…an*(2a1*10n-1-1)
A2A2…An对于我们考虑的值大于n-1。
因此,剩下来证明用10n-1除差的就是5n-1除2a1*10n-1-1。为此,我将使用欧拉定理: 2phi(5n-1)=1(模5n-1) 现在phi(5n-1)=4*(5n-2),对于n>=34*(5n-2)将除以a1*10n-1(实际上甚至仅仅是10n-1) 因此2a1*10n-1给出模5n-1的余数1,因此5n-1除以2a1*10n-1-1 因此,10n-1将2a2a2…an*(2a1*10n-1-1)除以,因此2a2a2a2…an和2a2a3a4…an的最后n-1位是相同的 现在,由于a1a2a2…an是有趣的,2a1a2a2…an的最后n位是a1a2a2…an,因此2a2a3a4…an的最后n-1位是a2a3a4…an,因此a2a3a4…an也是有趣的。QED
使用这个引理,您将能够解决这个问题。请注意,您也可以预先添加一些零,然后添加一个非零数字。在20个增量后,最后的数字开始重复。因此,对于任何带有最后数字1的n,答案的最后数字将是2。因此,大多数n值可以立即消除 2^1=2
2^21=2097152
2^101=2535301200456458802993406410752
2^2=4
2^22=4194304
2^42=439804651104
事实上,只有两种可能共用最后一个数字:
2^14=16384
2^16=65536
2^34=17179869184
2^36=68719476736
如果n是14+20x或16+20x,那么它可能会工作,因此您需要检查它。否则,它将无法工作。我对此类问题不是很在行。但模幂运算似乎是您的关键。 对A到B范围内的所有n重复此操作:
1.查找k,n中的位数。这可以在O(logn)中完成
2.使用模幂运算找到2^n(mod 10^k),并检查它是否等于n。这需要O(n)个时间。(实际上,O(n)个乘法) 编辑
事实上,不要对每个n重复整个过程。给定2^n(mod 10^k),我们可以在恒定时间内找到2^(n+1)(mod 10^k)。利用这个事实进一步加速 编辑-2
这不适用于如此大的范围。一般来说,您可以通过在输出中找到一些模式来尝试解决这些问题。我们的团队在比赛中接受了这个问题。我们的方法是在满足标准的值中找到一个通用模式。如果您打印前几个这样的数字,那么您将找到以下模式
36
736
8736
48736
948736
因此,948736之后的下一个数字应该是7位数字,可以是1948736、2948736、3948736、4948736、5948736、6948736、7948736、8948736、9948736中的任意一位。因此,请检查哪个值有效,您就有了下一个数字。继续以这种方式,您可以返回自己获得所有150个数字
但这里有一个问题。将“1”添加到“9”后,会有一些数字不会立即跟随上一个数字。要解决此问题,您现在可以开始添加从10到99的值,然后检查是否有有效数字。如果仍然没有有效数字,请再次尝试添加从100到999的数字
现在使用这种方法,您将获得满足问题中给出的标准的所有137个值,并轻松回答所有查询。例如,显示了实现这一点的工作java代码。它将打印所有137个值
import java.io.*;
import java.math.*;
import java.util.*;
class Solution
{
public static void main(String[] args)throws java.lang.Exception{
new Solution().run();
}
void run()throws java.lang.Exception{
BigInteger[] powers = new BigInteger[152];
powers[0] = one;
for(int i=1; i<=150; i++){
powers[i] = powers[i-1].multiply(ten);
}
BigInteger[] answers = new BigInteger[152];
answers[2] = BigInteger.valueOf(36);
answers[3] = BigInteger.valueOf(736);
int last = 3;
for(int i=4; i<=150; i++){
int dif = i-last;
BigInteger start = ten.pow(dif-1);
BigInteger end = start.multiply(ten);
while(start.compareTo(end) < 0){
BigInteger newVal = powers[last].multiply(start);
newVal = newVal.add(answers[last]);
BigInteger modPow = pow(two, newVal, powers[i]);
if(modPow.equals(newVal)){
answers[i] = newVal;
System.out.println(answers[i]);
last = i;
break;
}
start = start.add(one);
}
}
}
BigInteger pow(BigInteger b, BigInteger e, BigInteger mod){
if(e.equals(zero)){
return one;
}
if(e.mod(two).equals(zero)){
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
return x;
}else{
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
x = x.multiply(two).mod(mod);
return x;
}
}
BigInteger ten = BigInteger.valueOf(10);
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger two = BigInteger.valueOf(2);
}
import java.io.*;
导入java.math.*;
导入java.util.*;
类解决方案
{
公共静态void main(字符串[]args)引发java.lang.Exception{
新解决方案().run();
}
void run()抛出java.lang.Exception{
BigInteger[]幂=新的BigInteger[152];
幂[0]=1;
对于(inti=1;i这是一个非常有趣的性质。在比赛中,我发现36是最重要的
36
736
8736
48736
948736
36
736
8736
48736
948736
import java.io.*;
import java.math.*;
import java.util.*;
class Solution
{
public static void main(String[] args)throws java.lang.Exception{
new Solution().run();
}
void run()throws java.lang.Exception{
BigInteger[] powers = new BigInteger[152];
powers[0] = one;
for(int i=1; i<=150; i++){
powers[i] = powers[i-1].multiply(ten);
}
BigInteger[] answers = new BigInteger[152];
answers[2] = BigInteger.valueOf(36);
answers[3] = BigInteger.valueOf(736);
int last = 3;
for(int i=4; i<=150; i++){
int dif = i-last;
BigInteger start = ten.pow(dif-1);
BigInteger end = start.multiply(ten);
while(start.compareTo(end) < 0){
BigInteger newVal = powers[last].multiply(start);
newVal = newVal.add(answers[last]);
BigInteger modPow = pow(two, newVal, powers[i]);
if(modPow.equals(newVal)){
answers[i] = newVal;
System.out.println(answers[i]);
last = i;
break;
}
start = start.add(one);
}
}
}
BigInteger pow(BigInteger b, BigInteger e, BigInteger mod){
if(e.equals(zero)){
return one;
}
if(e.mod(two).equals(zero)){
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
return x;
}else{
BigInteger x = pow(b, e.divide(two), mod);
x = x.multiply(x).mod(mod);
x = x.multiply(two).mod(mod);
return x;
}
}
BigInteger ten = BigInteger.valueOf(10);
BigInteger zero = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
BigInteger two = BigInteger.valueOf(2);
}
def powm(i):
j = 10
a = 1
while i:
if i % 2:
a = a * j
i /= 2
j *= j
return a
def power(n, i):
m = powm(i)
y = 1
x = 2
while n:
if n % 2 == 1:
y = y * x % m
x = x * x % m
n /= 2
return y
mylist = []
mylist.append(power(36, 2))
n = mylist[0]
print(n)
for i in range(3, 170):
p = power(n, i)
print p
if p != n:
mylist.append(p)
n = p
t = input()
while t:
x = raw_input().split(" ")
a = int(x[0])
b = int(x[1])
i = 0
#while i <= 150:
#print mylist[i]
#i += 1
#print power(8719476736,14)
while mylist[i] < a:
i += 1
ans = 0
while mylist[i] <= b:
i += 1
ans += 1
print ans
t -= 1