洛谷P3811【模板】乘法逆元
? 解题记录 ? ? 洛谷 ? ? 扩展欧几里得 ? ? 模板 ?    2017-08-21 17:17:21    554    0    0

题目背景

这是一道模板题

题目描述

给定n,p求1~n中所有整数在模p意义下的乘法逆元。

输入输出格式

输入格式:

 

一行n,p

 

输出格式:

 

n行,第i行表示i在模p意义下的逆元。

 

输入输出样例

输入样例#1:
10 13
输出样例#1:
1
7
9
10
8
11
2
5
3
4

说明

1 \leq n \leq 3 \times 10 ^ 6, n < p < 200005281n3×106,n<p<20000528

输入保证 pp 为质数。

突然觉得之前太傻了……居然拿逆元硬转成了线性方程, 强行扩欧,时间复杂度爆棚。

其实我们推一下式子可以发现:求a mod b的逆元,a、b 在mod b下有以下性质:

1、a * 1 = a

2、a * 0 = mod

然后我们又发现,a和mod一定是互质的,因为如果不互质除运算时没有意义的。也就是说,如果对右边的式子做辗转相除,同时记录左边的数字,最后一定能得到a * m = 1 (在mod的意义下) ,就求出了逆元!

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int ext_gcd(int a, int b, int c, int d) {
	return d != 1 ? ext_gcd(b, a - (c / d) * b, d, c % d) : b;
}

int main() {
	int a, b;
	scanf("%d%d", &a, &b);
	for(register int i = 1; i <= a; ++i) {
		int ans = ext_gcd(0, 1, b, i);
		if(ans < 0) ans = ans + ((0 - ans) / b + 1) * b;
		printf("%d\n", ans);
	}	
	return 0;
}

 但是其实可以线推的,看这篇博客:我是“这篇博客”。然后时间复杂度变成了O(n)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 3e6 + 10;
int n, mod;
int inv[maxn];

int main() {
	inv[1] = 1;
	scanf("%d%d", &n, &mod);
	printf("1\n");
	for(register int i = 2; i <= n; ++i) {
		inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod;
		printf("%d\n", inv[i]);
	}
	return 0;
}

 

上一篇: 洛谷P2158 [SDOI2008]仪仗队

下一篇: 洛谷P2679 子串

554 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航