HDU 4910 Problem about GCD(米勒拉宾)

HDU 4910 Problem about GCD

题目链接

题意:给定一个数字,求出1 - n之间与他互质的数的乘积mod n

思路:看了网上别人找出来的规律,原文链接

然后由于这题的n很大,也没法直接判定,可以这样搞,先去试10^6以内的素数,判断可不可以,如果不行,再利用米勒拉宾判下是否是素数,如果不是的话,把这个数字开根在平方,判断是不是完全平方数,这样做的原因是数字最大10^18,如果没有10^6以内的质因子,又不是质数的话,那么他最多只能包含2个质因子了,那么如果他不是一个完全平方数的话,那么就肯定不是了

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>

typedef long long ll;

const int N = 1000005;
ll n, prime[N];
int vis[N], pn;

ll mul(ll a, ll b, ll mod) {
    ll ret = 0;
    while (b > 0) {
	if (b&1) ret = (ret + a) % mod;
	b >>= 1;
	a = (a<<1) % mod;
    }
    return ret;
}

ll pow_mod(ll x, ll k, ll mod) {
    ll ans = 1;
    while (k) {
	if (k&1) ans = mul(ans, x, mod);
	x = mul(x, x, mod);
	k >>= 1;
    }
    return ans;
}

bool mlrb (ll n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    for (int i = 0; i < 20; i++) {
	ll a = rand() % (n - 1) + 1;
	if (pow_mod(a, n - 1, n) != 1)
	    return false;
    }
    return true;
}

void get_table() {
    pn = 0;
    for (ll i = 2; i < N; i++) {
	if (vis[i]) continue;
	prime[pn++] = i;
	for (ll j = i * i; j < N; j += i)
	    vis[j] = 1;
    }
}

bool check(ll n) {
    for (int i = 1; i < pn; i++) {
	if (n % prime[i] == 0) {
	    ll tmp = n;
	    while (tmp % prime[i] == 0)
		tmp /= prime[i];
	    if (tmp == 1)
		return true;
	    else
		break;
	}
    }
    if (mlrb(n)) return true;
    ll m = (ll)sqrt(n * 1.0);
    if (m * m == n) return true;
    return false;
}

bool judge(ll n) {
    if (n == 1 || n == 2 || n == 4) return true;
    if (n % 4 == 0) return false;
    if (n % 2 && check(n)) return true;
    if (n % 2 == 0 && check(n / 2)) return true;
    return false;
}

int main() {
    get_table();
    while (~scanf("%I64d", &n) && n != -1) {
	if (judge(n)) printf("%I64d\n", n - 1);
	else printf("1\n");
    }
    return 0;
}

HDU 4910 Problem about GCD(米勒拉宾),布布扣,bubuko.com

时间: 2024-10-13 05:13:48

HDU 4910 Problem about GCD(米勒拉宾)的相关文章

HDU 4910 Problem about GCD

Problem about GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 470    Accepted Submission(s): 77 Problem Description Given integer m. Find multiplication of all 1<=a<=m such gcd(a, m)=1 (cop

hdu 4910 Problem about GCD(数论)

题目连接:hdu 4910 Problem about GCD 题目大意:给定M,判断所有小于M并且和M互质的数的积取模M的值. 解题思路:有个数论的结论,若为偶数,M=M/2. 可以写成M=pk,即只有一种质因子时,答案为M-1,否则为1.特殊情况为4的倍数,不包括4. 首先用1e6以内的素数去试除,如果都不可以为p,那么对大于1e6的情况判断一下是否为素数,是素数也可以(k=1),否则开方计算,因为M最大为1e18,不可能包含3个大于1e6的质因子. #include <cstdio> #

HDU 2138 How many prime numbers (判素数,米勒拉宾算法)

题意:给定一个数,判断是不是素数. 析:由于数太多,并且太大了,所以以前的方法都不适合,要用米勒拉宾算法. 代码如下: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> #include <map> #include <cctype> u

POJ 1811Prime Test(米勒拉宾素数测试)

直接套用模板,以后接着用 这里还有一个素因子分解的模板 1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10

米勒-拉宾素性测试学习

之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则有 a^(p-1) = 1 (mod p) 基于以下定理 若(a, p)=1,{x| (x, p)=1}为模p下的一个完全剩余系,则{ax| (x, p)=1}也为模p下的一个完全剩余系. 又{0, 1, 2, ... p-1}为模p下一个剩余系   因此有, {a*0, a*1, a*2, ... a*(p

米勒-拉宾(MillerRabbin)素性测试算法

首先,在了解米勒-拉宾素性测试之前,我们要先了解费马小定理. 关于费马小定理就不再细说原理和证明了,应用非常广泛. 费马小定理中说  若p是质数  则有 a的(p-1)次方在(mod p)的情况下 恒等于1   数学表达式--->  a^(p-1) ≡ 1 (mod p) 然后我们要注意: p若是质数  则满足费马小定理  但是  满足费马小定理  并不能证明p就是质数 有些数字 满足费马小定理,但是并不是质数  他们叫做伪质数(伪素数的个数是无穷的) 那么 知道了这些  算法就很好理解了 一个

csu 1552(米勒拉宾素数测试+二分图匹配)

1552: Friends Time Limit: 3 Sec  Memory Limit: 256 MBSubmit: 723  Solved: 198[Submit][Status][Web Board] Description On an alien planet, every extraterrestrial is born with a number. If the sum of two numbers is a prime number, then two extraterrestr

HDU2138 &amp; 米勒拉宾模板

题意: 给出n个数,判断它是不是素数. SOL: 米勒拉宾裸题,思想方法略懂,并不能完全理解,所以实现只能靠背模板.... 好在不是很长... Code: /*========================================================================== # Last modified: 2016-03-21 10:09 # Filename: miller-rabin.cpp # Description: =================

Miller_Rabin(米勒拉宾)素数测试

2018-03-12 17:22:48 米勒-拉宾素性检验是一种素数判定法则,利用随机化算法判断一个数是合数还是可能是素数.卡内基梅隆大学的计算机系教授Gary Lee Miller首先提出了基于广义黎曼猜想的确定性算法,由于广义黎曼猜想并没有被证明,其后由以色列耶路撒冷希伯来大学的Michael O. Rabin教授作出修改,提出了不依赖于该假设的随机化算法. 问题描述:对于大整数N,判断其是否为素数. 问题求解: 若N为偶数,直接返回false,若N是奇数,则进行以下几步进行判断: 将N -