【题目描述】
设数列{an}满足如下递推式:
ai=(ai-1+1234567890) mod 2^31,其中i>=2.
给定a1,判断a1,a2,…,a100000是否是素数。若是输出1,否则输出0。
【输入格式】
一行一个正整数a1,在int范围内。
【输出格式】
一行,一个长度为100000的01串。第i项个字符对应ai是否为素数。若是则为1,不是则为0。
【样例输入】
1
【样例输出】
答案串的前50项为:
01000000000000000000000000001000010000000001100000
【提示】
这里的输入输出格式和SPOJ上原题不同。
数列的第一项为1(非素数),第二项为1234567891(素数),以此类推。
mirller rabin算法是一个概率算法,可以快速求解出一个数是否为素数
在 int 范围内, 只需测试 2、 7、 61, 这也是信息学竞赛中最常用的
在 int64(1E16) 范围内, 只需测试 2、 3、 7、 61、 24251, 并排除 46 856 248 255 981 这个强伪素数。
设要求n是否为素数
n - 1 = d * 2 ^ r //需要保证d mod 2= 1if a^d mod n == 1 || a^d mod n == n - 1?n is primelse if a^(d * 2^i) mod n == n - 1 // i∈[1, r]n is primelsen is not prim
粘代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define maxn 1000050
using namespace std;
long long pow(long long a, long long x, long long m)
{
if (x == 0)
return 1;
if (x == 1)
return a % m;
long long t = pow(a, x / 2, m);
if (x & 1)
return ((t * t) % m) * a % m;
else
return (t * t) % m;
}
inline bool test(long long n, long long a, long long d)
{
long long t = pow(a, d, n);
if (t == 1 || t == n - 1)
return true;
while (d != n - 1)
{
d <<= 1;
t = t * t % n;
if (t == n - 1)
return true;
}
return false;
}
inline bool miller_rabin(long long n)
{
if (n == 2 || n == 7 || n == 61)
return true;
if (n < 2 || ~n & 1)
return false;
long long d = n - 1;
while (~d & 1)
d >>= 1;
if (test(n, 2, d) && test(n, 7, d) && test(n, 61, d))
return true;
return false;
}
int main(){
freopen(“primechecker.in”, “r”, stdin);
freopen(“primechecker.out”, “w”, stdout);
int a;
scanf(“%d”, &a);
for (int i = 1; i < 100000; ++i)
{
printf(“%d”, (int)miller_rabin(a));
a = a + 1234567890 & 0x7fffffff;
}
printf(“%d\n”, (int)miller_rabin(a));
return 0;
}