线性同余方程是同余方程中最基础的内容。
【模板】裴蜀定理
题目描述
给定一个包含 n n n 个元素的整数序列 A A A,记作 A 1 , A 2 , A 3 , . . . , A n A_1,A_2,A_3,...,A_n A1,A2,A3,...,An。
求另一个包含 n n n 个元素的待定整数序列 X X X,记 S = ∑ i = 1 n A i × X i S=\sum\limits_{i=1}^nA_i\times X_i S=i=1∑nAi×Xi,使得 S > 0 S>0 S>0 且 S S S 尽可能的小。
输入格式
第一行一个整数 n n n,表示序列元素个数。
第二行 n n n 个整数,表示序列 A A A。
输出格式
一行一个整数,表示 S > 0 S>0 S>0 的前提下 S S S 的最小值。
样例 #1
样例输入 #1
2
4059 -1782
样例输出 #1
99
提示
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, ∣ A i ∣ ≤ 1 0 5 |A_i| \le 10^5 ∣Ai∣≤105,且 A A A 序列不全为 0 0 0。
解题思路
code
#include<iostream>
#include<cmath>
using namespace std;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int n;
cin>>n;
int s;
cin>>s;
for(int i=2,a;i<=n;i++)
{
cin>>a;
s=gcd(abs(a),s);
}
cout<<s;
return 0;
}
【模板】有理数取余
题目描述
给出一个有理数 c = a b c=\frac{a}{b} c=ba,求 c m o d 19260817 c \bmod 19260817 cmod19260817 的值。
这个值被定义为 b x ≡ a ( m o d 19260817 ) bx\equiv a\pmod{19260817} bx≡a(mod19260817) 的解。
输入格式
一共两行。
第一行,一个整数
a
a
a。
第二行,一个整数
b
b
b。
输出格式
一个整数,代表求余后的结果。如果无解,输出 Angry!
。
样例 #1
样例输入 #1
233
666
样例输出 #1
18595654
提示
对于所有数据,保证 0 ≤ a ≤ 1 0 10001 0\leq a \leq 10^{10001} 0≤a≤1010001, 1 ≤ b ≤ 1 0 10001 1 \leq b \leq 10^{10001} 1≤b≤1010001,且 a , b a, b a,b 不同时是 19260817 19260817 19260817 的倍数。
解题思路
本题在快读时实现取模,直接当作非大整数的做法来求。
code
#include<iostream>
using namespace std;
#define MOD 19260817
int a,b;
long long x,y;
void read(int&x){
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10%MOD+(s-'0')%MOD;s=getchar();}
x=x%MOD*f;
}
int exgcd(int a,int b,long long&x,long long&y)
{
if(b==0)
{
x=1,y=0;
return a;
}
long long x1,y1;
int d=exgcd(b,a%b,x1,y1);
x=y1,y=x1-a/b*y1;
return d;
}
int main()
{
read(a);
read(b);
int d=exgcd(b,MOD,x,y);
if(a%d==0)cout<<(x*a/d%MOD+MOD)%MOD<<endl;
else cout<<"Angry!"<<endl;
return 0;
}
【模板】模意义下的乘法逆元
题目背景
这是一道模板题
题目描述
给定 n , p n,p n,p 求 1 ∼ n 1\sim n 1∼n 中所有整数在模 p p p 意义下的乘法逆元。
这里 a a a 模 p p p 的乘法逆元定义为 a x ≡ 1 ( m o d p ) ax\equiv1\pmod p ax≡1(modp) 的解。
输入格式
一行两个正整数 n , p n,p n,p。
输出格式
输出 n n n 行,第 i i i 行表示 i i i 在模 p p p 下的乘法逆元。
样例 #1
样例输入 #1
10 13
样例输出 #1
1
7
9
10
8
11
2
5
3
4
提示
$ 1 \leq n \leq 3 \times 10 ^ 6 , , ,n < p < 20000528 $。
输入保证 $ p $ 为质数。
代码实现
#include<iostream>
using namespace std;
#define MAX_N 3000000
int inv[MAX_N+5];
int main()
{
int n,p;
cin>>n>>p;
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=(long long)(p-(p/i))*inv[p%i]%p;
for(int i=1;i<=n;i++)
printf("%d\n",inv[i]);
return 0;
}
解题思路
本题需要求出若干连续数的逆元,可以使用递推的方法来求。
code
#include<iostream>
using namespace std;
#define MAX_N 3000000
int inv[MAX_N+5];
int main()
{
int n,p;
cin>>n>>p;
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=(long long)(p-(p/i))*inv[p%i]%p;
for(int i=1;i<=n;i++)
printf("%d\n",inv[i]);
return 0;
}
[NOIP2012 提高组] 同余方程
题目描述
求关于 $ x$ 的同余方程 $ a x \equiv 1 \pmod {b}$ 的最小正整数解。
输入格式
一行,包含两个整数 a , b a,b a,b,用一个空格隔开。
输出格式
一个整数 x 0 x_0 x0,即最小正整数解。输入数据保证一定有解。
样例 #1
样例输入 #1
3 10
样例输出 #1
7
提示
数据规模与约定
- 对于 40 % 40\% 40% 的数据, 2 ≤ b ≤ 1 , 000 2 ≤b≤ 1,000 2≤b≤1,000;
- 对于 60 % 60\% 60% 的数据, 2 ≤ b ≤ 50 , 000 , 000 2 ≤b≤ 50,000,000 2≤b≤50,000,000;
- 对于 100 % 100\% 100% 的数据, 2 ≤ a , b ≤ 2 , 000 , 000 , 000 2 ≤a, b≤ 2,000,000,000 2≤a,b≤2,000,000,000。
code
#include<iostream>
using namespace std;
int exgcd(int a,int b,int&x,int&y)
{
if(b==0)
{
x=1,y=0;
return a;
}
int x1,y1;
int d=exgcd(b,a%b,x1,y1);
x=y1,y=x1-a/b*y1;
return d;
}
int main()
{
int a,m,x,y;
cin>>a>>m;
int d=exgcd(a,m,x,y);
cout<<(long long)(x%m+m)%m<<endl;
return 0;
}