使用以下约束计算三元组

时间:2015-02-23 18:16:12

标签: algorithm

给定A,B,C和D,我们需要在约束x≤A,y≤B下找到三元组(x,y,z)的数量,使得((x x或y)或z)≤D, z≤C其中A,B,C和D各自可达10 ^ 18。

由于答案可能非常大,我们需要输出模数为10 ^ 9 + 7的三元组数。

基本且效率低下的方法:

i=0,j=0,k=0,ans=0

FOR (i<=A)

   FOR(j<=B)

     FOR(k<=C)

        if(((i^j)|k)<=D) ans=ans+1

print ans%1000000007

显然效率非常低,可以采取更好的方式吗?

3 个答案:

答案 0 :(得分:0)

这是一个开始的想法。选一个数字r。如果i ^ j = r,并且给出了i,j的可能值是多少?提示:只有一个。

如果只有0≤i≤A的条件,那么很容易找到i ^ j = r的解的个数。现在有两个条件,0≤i≤A和0≤j≤B。这有点困难。发布解决方案,然后我们继续。

解决这个小问题需要将执行时间从O(n ^ 3)降低到O(n ^ 2),这使得有可能求解A,B,C,D≤10^ 6这是不可能的你的算法。

答案 1 :(得分:0)

我们可以通过将数字(x,y,z)分成比特来解决问题。因为x,y,z <= 10 ^ 18,所以每个数字小于 50位

所以从第一位开始到第50位,我们需要知道四件事

  • x是否小于A
  • y是否小于B
  • z是否小于C
  • (x ^ y) | z是否小于D

所以,我们有我们的功能:

long totalNumber(int bit, boolean lessThanA, boolean lessThanB, boolean lessThanC, boolean lessThanD)

对于每个位位置,我们只需要为每个数字x,y,z尝试位0和位1

    long result = 0;
    for(int x = 0; x < 2; x++){
       for(int y = 0; y < 2; y++){
          for(int z = 0; z < 2; z++){
             //update lessThanA, lessThanB, lessThanC, lessThanD. This step is omitted.
             result += totalNumber(bit + 1, lessThanA, lessThanB, lessThanC, lessThanD);
             result %= MOD; //remember to take modulo of the result. 
          }
       } 
    }

对于我们的基本情况,如果我们达到第50位,则返回1

if(bit == 50)
   return 1;

因此,在这种情况下应用动态编程,我们有一个表

dp[bit][lessThanA][lessThanB][lessThanC][lessThanD]

并且时间复杂度将降低到O(bit * lessThanA * lessThanB *lessThanC * lessThanD),即O(50*2^4) = O(800)

最后注意事项:今天的编程竞赛中经常会出现这种类型的问题。举一个例子,看看problem B round 1B Google Code Jam 2014

答案 2 :(得分:0)

由于问题涉及逐位操作,让我们考虑二进制示例:

x = ???????????????????

y = ???????????????????

z = ???????????????????

D = 1100000011001101010 (binary)

假设我们可以创建一个方法(可能是组合),将其称为f(D),以计算可以合并比特的方式以准确地产生D。这是考虑低于D的数字的一种方法:

(1) Any number without the highest bit D has set: 
    _xxxxxxxxxxxxxxxxxx

(2) Any number with the highest bit D has set, but without the next highest bit D has set:
    10xxxxxxxxxxxxxxxxx

(3) Any number with the highest bit and the next highest bit D has set, but without the 
    third highest bit D has set:    
    110000000xxxxxxxxxx

 And so on...

(1),(2),(3)等中的每一个都是用于组合计算可能的三元组的独特机会,其中可以使用我们先前的方法计算产生已经填充的比特的方式, fx可以轻松计算为所有可能的组合。