找到可被1到N之间所有数字整除的最小数字,剩余数= 0

时间:2015-06-07 18:07:46

标签: c++ algorithm

找到可从1到N的所有数字整除的最小数字,不留任何余数。由于数字可能非常大,我们采用模数1000000007的答案。

我认为可以被1到N的所有数字整除的最小数字是LCM(1..N)。

示例:对于N = 5,最小的数字为60。

因为60是可以被所有数字形式整除的最小数字(1-5)。

但是由于一些奇怪的原因,它给了我大的N(1000)等的错误答案。 什么可能导致可能的错误,我的登录在这里是正确的吗?

这是我试图实施的内容。

#include <iostream>
#include <vector>
using namespace std;

vector<long long> lcmArr;
const long long mod = 1000000007;

long long gcd(long long a, long long b){
    if(b == 0) 
    {
        return a;
    }

    return gcd(b, a%b);
}

long long lcmFumction(long long  a, long long  b)
{
    return (a*b)/gcd(a,b);  
}

int main() {
    lcmArr.clear();lcmArr.resize(1002);
    lcmArr[0] =0; lcmArr[1] = 1;
    for(int i =2; i <=1000; i++){
        lcmArr[i] = lcmFumction(lcmArr[i-1], i)%mod;
            //cout<<lcmArr[i-1]<<" ";
    }

    int T;
    cin >> T;
    while(T--) {
        int N;
        cin>>N;
        cout<<lcmArr[N]<<"\n";
    }
    return 0; 
}

2 个答案:

答案 0 :(得分:6)

问题是当你计算LCM时,你使用除法,

并且

((A/B)/C) mod M != (((A/B) mod M)/C)mod M

例如(10/5/2) % 2 != ((10/5)%2)/2)%2

您应该使用modular inverse来计算。

关于模逆的一些解释。

如果我们有:

(a*b) % m = 1,然后ba呈模块化反转,为b % m = (1/a) % m

因此,如果我们需要计算(x/a) % m,我们可以将其变为(x * b ) %m

我们知道(A*B*C)% m = ((A * B) % m)*C)% m,因此,在您的情况下,模块化逆会派上用场。

答案 1 :(得分:1)

我知道上面的答案已被接受,但我认为这还不足以解决您的问题。问题在于第一个模块化LCM将带走您在后续GCD呼叫中检查所需的所有除数,因此答案仍然是错误的。

一种可能的解决方案是为答案保留一系列因素。每个因子将是1..N中的每个数字,除以GCD(数字,[所有以前的数字])。为此,您必须编写一个特殊的GCD代码,用于计算单个数字和一系列因子之间的结果。这个C ++代码显示了它的工作原理:

#include <iostream>
#include <vector>
#define lli long long int
using namespace std;

vector<lli> T;

lli gcd(lli a, lli b) {
    if(b == 0) 
        return a;
    return gcd(b, a%b);
}

lli gcd_vector(vector<lli>& a, lli b) {
    lli ma = 1;
    for(int i=0; i<T.size(); i++)
        ma = ma*T[i]%b;
    return gcd(b, ma);
}

int main() {
    lli answer = 1;
    for(int i=1; i<=1000; i++) {
        lli factor = i/gcd_vector(T, i); 
        T.push_back(factor);
        answer = (answer*factor)%1000000007;
    }

    cout << answer << endl;
}