码迷,mamicode.com
首页 > 其他好文 > 详细

COJ0700 数学(一)

时间:2015-07-15 19:03:43      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

试题描述
现在有一大堆数,请你对这些数进行检验。
输入
第一行:CAS,代表数据组数(不大于500000),以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。你需要对于每个数字检验是否是质数。
输出
共一行,输出质数的数量,保证是在64位长整形范围内的正数。
输入示例
4 2 3 5 4
输出示例
3
其他说明
数据范围: 保证cas<=100000,保证所有数字均在64位长整形范围内。 请尽量优化你的程序,包括OI优化。 欢迎暴力法不服来辩呦→ →

 首先有这样一个定理:

若p是一个质数,x是一个整数,且x^2 mod p = 1,那么x ≡ ±1 (mod p)。

证明:x^2 mod p = 1       ->       p | x^2 - 1        ->       p | (x - 1)(x + 1),又因为p是质数故x-1与x+1中有一个是p的倍数。

但这个定理的逆定理是个假命题,不过它很少有反例。我们就可以利用逆定理来判定素数了。

设待测数为n,任取一个比n小的正整数a,设 n - 1 = r * 2^s,若n是质数则以下条件至少有一个成立:
1.a^s mod n = 1

2.存在一个整数i满足:0<=i<s且a^(d*(2^i)) mod n = -1

重复以上步骤3至4次即可稳定出解。

技术分享
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-0;
    return x*f;
}
typedef long long ll;
ll pow(ll n,ll m,ll p) {
    ll ans=1,t=n;
    while(m) {
        if(m&1) (ans*=t)%=p;
        (t*=t)%=p;m>>=1;
    }
    return ans;
}
int check(ll a,ll n,ll r,ll s) {
    ll ans=pow(a,r,n);if(ans==1) return 0;
    rep(1,s) {
        if(ans==n-1) return 0;
        (ans*=ans)%=n;
    }
    return 1;
}
int isprime(ll n) {
    if(n==2) return 1;
    if(n<=1||!(n&1)) return 0;
    int r=n-1,s=0;
    while(!(r&1)) r>>=1,s++;
    rep(1,3) if(check(rand()%(n-1)+1,n,r,s)) return 0;
    return 1;
}
int main() {
    int T=read(),ans=0;
    while(T--) ans+=isprime(read());
    printf("%d\n",ans);
    return 0;
}
View Code

 

COJ0700 数学(一)

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/4648930.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!