我必须编写一个程序,以便对于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;
}
}
答案 0 :(得分:1)
您可以使用segment tree。我们的想法是在表示区间l, l+1, ..., r
的每个节点中存储[l, r]
的最小公倍数。
如何构建 - 您自下而上开始,当您必须合并到节点[a, b]
,[b+1, c]
时,您将执行以下操作。让lcm([a, b]) = l1
和lcm([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
的数据结构。我不会提供代码,因为这不是我们在这里所做的。
此链接:
对你有所帮助。
答案 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也可以在这里使用。