更好的算法来检查数字既不是素数也不是单个素数的幂

时间:2017-01-25 17:32:42

标签: c++ algorithm

我有以下程序,其中 t 可以取值1到100000,而 n 可以取值1到10 ^ 9。

#define MAX 10000000

using namespace std;

unordered_set<long long int> s;

bool morethanone(long long int n)
{
    long long int check=0;
    for(unordered_set<long long int>::iterator it=s.begin();it!=s.end();it++)
    {
        if(n%(*it)==0)
            check++;
        if(check>1)
            return false;
    }
    return true;
}

bool isprime(long long int n)
{
    if(n%2==0)
        return false;
    for(long long int i=3;i<=sqrt(n);i+=2)
        if(n%i==0)
            return false;
    return true;
}

int main() 
{
s.insert(2);
s.insert(3);
for(long long int i=4;i<=MAX;i++)
{
        if(isprime(i))
            s.insert(i);
}

long long int t,n;
scanf("%lld",&t);
for(long long int test=0;test<t;test++)
{
    scanf("%lld",&n);
    if(n==1||s.find(n)!=s.end())
        cout<<"Santa\n";
    else if(morethanone(n))
        cout<<"Santa\n";
    else
        cout<<"Banta\n";
}

return 0;
}

基本上,该程序生成素数直到10 ^ 9并打印&#34; Santa&#34;如果给出的数字是素数或单个素数的幂或1。

上述程序适用于MAX = 10 ^ 6,但显示&#34;由于超时终止&#34;除了那之外的任何价值。

2 个答案:

答案 0 :(得分:1)

您想确定 n 是否可以使用 p prime和 k写入 p k &gt; 0积分。

Henri Cohen描述了他的书计算代数数论中的课程的算法1.7.5中的答案。他利用费马的小定理,见证了米勒 - 拉宾素性测试者发现的 n 的复合性。 Cohen证明,如果 a n 复合性的见证,那么在Miller-Rabin测试的意义上,那么gcd( a n < / sup> - a n )是 n 的一个重要的除数(也就是说,它在1和名词的)。

我将这个想法减少为 http://ideone.com/cNzQYr的Python代码,并在my blog给出更全面的解释。这是来自ideone.com的有趣代码,因为Stack Overflow不会让我在没有它的情况下发帖;去那儿看其余的:

# returns p,k such that n=p**k, or 0,0
# assumes n is an integer greater than 1
def primePower(n):
    def checkP(n, p):
        k = 0
        while n > 1 and n % p == 0:
            n, k = n / p, k + 1
        if n == 1: return p, k
        else: return 0, 0
    if n % 2 == 0: return checkP(n, 2)
    q = n
    while True:
        a = findWitness(q)
        if a == 0: return checkP(n, q)
        d = gcd(pow(a,q,n)-a, q)
        if d == 1 or d == q: return 0, 0
        q = d

答案 1 :(得分:0)

有许多高级方法可以快速计算素数,但改进代码的一种简单方法是仅检查下一个候选数字是否可被目前为止找到的素数之一整除。当您将素数保留在允许排序的数据结构中时,一旦达到大于候选数字的平方根的素数,就可以停止。

如评论中所述,也可以在块中进行筛分,并且可以与上述改进相结合。现在你只检查实际上是块大小为2的奇数。如果你检查了候选者不能被3整除,你可以用块大小6来检查。这意味着省略块和位置中的每个偶数位置一个(基于一个)的索引可以被3整除,所以只有索引1和5.依此类推......

还可以改进检查数字是否是单个素数的幂。一旦找到一个可以被整除的素数,检查它是否是这个素数的幂(写另一种方法)并立即停止。