随笔 - 68  文章 - 57  trackbacks - 0
<2009年3月>
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(8)

随笔分类(74)

随笔档案(68)

搜索

  •  

最新评论

阅读排行榜

评论排行榜

基本的判素都比较慢,对于这个题目的BT数据量(2 ^ 31),也只能用概率判素模型了。
Miller-Rabin基于费马小定理:如果(a, p) = 1,那么a ^ (p - 1) = 1 mod p。满足这个性质的p叫伪素数,如果一个数是伪素数,那么它有很大可能是素数。通过多次的枚举a,利用快速幂取模判断,就可以知道p是不是素数,Miller-Rabin测试的成功率在3/4。
费马小定理是该定理的特殊形式:如果p是素数,那么对于任意整数a:a ^ p = a mod p。这个定理可以用归纳法证明,证明依据这样一个事实:组合数C(n, k)是一个整数,如果n是素数,那么n和k!、(n - k)!的每一项都互素,可以提出n,也就是C(n, k) / n也是整数,所以n | C(n, k)。
这个题目的代码如下:
#include <cstdio>
#include 
<stdlib.h>
const int MAX = 4, N = 1000000;

long long PowerMod(long long a, long long b, long long k)
{
    
long long ret = 1, f = a;

    
while (b)
    
{
        
if (b & 1)
            ret 
= ret * f % k;
        f 
= f * f % k;
        b 
>>= 1;
    }

    
return ret;
}

bool MillerRabin(long long n)
{
    
int i;
    
long long tmp;

    srand(
100);
    
for (i = 0; i < MAX; i++)
    
{
        tmp 
= rand() % (n - 1+ 1;
        
if (PowerMod(tmp, n - 1, n) != 1)
            
break;
    }

    
return (i == MAX);
}


int main()
{
    
long long n, i, j;
    
bool tag[N] = {110};

    
for (i = 2; i * i < N; i++)
    
{
        
if (tag[i]) continue;
        
for (j = i; j * i < N; j++)
            tag[j
*i] = 1;
    }

    
while (scanf("%lld"&n) == 1)
    
{
        
if (n < N)
            printf(
"%s\n", tag[n] ? "NO" : "YES");
        
else
            printf(
"%s\n", ((n & 1== 0|| !MillerRabin(n) ? "NO" : "YES");
    }


    
return 0;
}

posted on 2009-03-18 21:15 sdfond 阅读(600) 评论(0)  编辑 收藏 引用 所属分类: Algorithm - Number Theory

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理