用于计算具有低复杂度的K个连续数mod 1000000007的LCM的程序

时间:2015-10-09 06:54:07

标签: c++ algorithm primes prime-factoring

我必须编写一个程序,以便对于L,R类型的几个查询 我必须输出从L到R的数字的LCM。 其中R最大可以到M

我已经管理过写一个复杂度为N(Q).M的程序, 我需要在N(Q).Log(M)或N(Q).sqrt(M)中进行。

这里N(Q)表示没有查询。 sqrt表示平方根。

编辑:我是用Segmentree写的,但得到了错误的答案,这里powf在登录时间内找到了^ b%P: 我的查询代码:

 long long findfunc(long long ql,long long qr,long long ind)
  {
 if(a >qr || b<ql)
   return 1;
 if(a>=ql && b<=qr)
  { //cout<<"LCM "<<ql<<" to "<<qr<<" "<<val[ind]<<endl; 
   return  val[ind]%mod;
  }
 else
  {
 ll vl= findfunc(ql,qr,2*ind+1);
 ll vr= findfunc(ql,qr,2*ind+2);
 return  ( ((vl*vr)%mod) * powf(gcd(vl,vr),mod-2)  )%mod;
 }  
}

3 个答案:

答案 0 :(得分:1)

您可以使用segment tree。我们的想法是在表示区间l, l+1, ..., r的每个节点中存储[l, r]的最小公倍数。

  • 如何构建 - 您自下而上开始,当您必须合并到节点[a, b][b+1, c]时,您将执行以下操作。让lcm([a, b]) = l1lcm([b+1, c]) = l2然后lcm([a, c]) = lcm(lcm([a, b]), lcm([b+1, c])) = lcm(l1, l2) = l1*l2 / gcd(l1,l2)。由于gcd(l1,l2)大致不变,因此合并操作是恒定的。

  • 如何查询 - 如果您有间隔[a, b],则在树中找到节点,使其代表范围[a, c]和{{1}对于某些[c+1, b]。然后c的计算与合并步骤中的计算相同。

答案 1 :(得分:0)

您正在寻找名为Segment Trees的数据结构。我不会提供代码,因为这不是我们在这里所做的。

此链接:

https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/

对你有所帮助。

答案 2 :(得分:0)

我不是C ++专家,你可以看看我的C#实现,我相信这并不难转换为C ++。

private const int Mid = 128 * 1024;
private static long mod = 1000000007;
private static long[] t = new long[Mid + Mid];
public static void Initialize(long[] a)
{
    for (int i = 0; i < a.Length; i++) t[Mid + i] = a[i];
    for (int i = a.Length; i < Mid; i++) t[Mid + i] = 1;
    for (int i = Mid - 1; i > 0; i--) t[i] = LCM(t[i + i], t[i + i + 1]);
}

public static long GetLcm(int l, int r)
{
    l += Mid;
    r += Mid;
    long ans = 1;
    while (l <= r)
    {
        ans = LCM(ans, t[l]);
        ans = LCM(ans, t[r]);

        l = (l + 1) / 2;
        r = (r - 1) / 2;
    }

    return ans;
}

public static void Update(int i, long v)
{
    i += Mid;
    t[i] = v;
    while (i > 0)
    {
        i = i / 2;
        t[i] = LCM(t[i + i], t[i + i + 1]);
    }
}

private static long GCD(long a, long b)
{
    if (a % b == 0) return b;
    return GCD(b, a % b);
}

private static long LCM(long a, long b)
{
    if (a == 0 || b == 0) return 0;
    return ((a * b) / GCD(a, b)) % mod;
}

您可以通过以下代码使用它:

    long[] m = new long[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    Initialize(m);
    var ans1 = GetLcm(0, 9);
    Update(8, 6);
    var ans2 = GetLcm(0, 9);

这不是优化的解决方案,但应该有效。 由于数据结构使用了分段树。 如果你真的不需要更新操作,SparseTable也可以在这里使用。