费马小定理 ( F e r m a t ′ s l i t t l e t h e o r e m ) (Fermat's little theorem) (Fermat′slittletheorem)是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有 a a a ^ \hat{} ^ ( p − 1 ) ≡ 1 ( m o d (p-1)≡1(mod (p−1)≡1(mod p ) p) p)
5 3 ≡ 1 ( m o d 5^3≡1(mod 53≡1(mod 2 ) 2) 2)
2 6 ≡ 1 ( m o d 2^6≡1(mod 26≡1(mod 7 ) 7) 7)
在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目
此函数以其首名研究者欧拉命名 ( E u l e r ′ s t o t i e n t f u n c t i o n ) (Euler's totient function) (Euler′stotientfunction),它又称为 E u l e r ′ s t o t i e n t f u n c t i o n Euler's totient function Euler′stotientfunction、 φ φ φ函数、欧拉商数等
然后就有 a a a φ ( n ) φ(n) φ(n) ≡ 1 ( m o d ≡1(mod ≡1(mod p ) p) p)
对于任意整数 a a a, b b b,存在一对整数 x x x, y y y,满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
int exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int z = x;
x = y;
y = z - y * (a / b);
return d;
}
自从曹冲搞定了大象以后,曹操就开始琢磨让儿子干些事业,于是派他到中原养猪场养猪,可是曹冲很不高兴,于是在工作中马马虎虎,有一次曹操想知道母猪的数量,于是曹冲想狠狠耍曹操一把。
举个例子,假如有 16 头母猪,如果建了 3 个猪圈,剩下 1 头猪就没有地方安家了;如果建造了 5 个猪圈,但是仍然有 1 头猪没有地方去;如果建造了 7 个猪圈,还有 2 头没有地方去。你作为曹总的私人秘书理所当然要将准确的猪数报给曹总,你该怎么办?
第一行包含一个整数 n ,表示建立猪圈的次数;
接下来 n 行,每行两个整数 a_i, b_i ,表示建立了 a_i 个猪圈,有 b_i 头猪没有去处。你可以假定 a_i,a_j 互质。
输出仅包含一个正整数,即为曹冲至少养猪的数目。
3 3 1 5 1 7 2
16
这道题有一种朴素算法
样例1
输入
2 3 1 5 2
% 3 = 1 : 1 、 4 \%3=1:1、4 %3=1:1、4、 7 7 7
、 10... 10... 10...
% 5 = 2 : 2 \%5=2:2 %5=2:2、 7 7 7
、 12... 12... 12...
输出
7 7 7
样例2
输入
3 3 1 5 2 7 3
% 3 = 1 : 1 、 4 \%3=1:1、4 %3=1:1、4、 7 7 7
、 10... 10... 10...
% 5 = 2 : 2 \%5=2:2 %5=2:2、 7 7 7
、 12... 12... 12...
% 3 = 1 且 % 5 = 2 : 7 、 22 、 37 \%3=1 且 \%5=2:7、22、37 %3=1且%5=2:7、22、37、 52 52 52
、 67... 67... 67...
% 7 = 3 : 3 、 10 、 17 、 24 、 31 、 38 、 45 \%7=3:3、10、17、24、31、38、45 %7=3:3、10、17、24、31、38、45、 52 52 52
、 59... 59... 59...
输出
52 52 52
#include
#include
#include
using namespace std;
const int M = 1e3 + 5;
int a, b, x, y;
int n;
queue <int > m1; //用两个队列来枚举
queue <int > m2;
void Calculation() {
m1.push(b), m2.push(y);
while (m1.back() != m2.back()) {
int p = m1.back(), q = m2.back();
if (p > q) {
m2.push((p - q + x - 1) / x * x + q);
}
if (p < q) {
m1.push((q - p + a - 1) / a * a + p);
}
}
b = m1.back(), a = a * x;
}
int main() {
scanf("%d", &n);
scanf("%d %d", &a, &b);
for(int i = 1; i < n; i ++) {
scanf("%d %d", &x, &y);
Calculation();
}
printf("%d", b);
return 0;
}
很不幸的是,我TLE了
中国剩余定理
#include
#include
using namespace std;
const int M = 15;
long long a[M], b[M];
long long x, y, m, k;
long long ans, mod = 1;
int n;
long long exgcd(long long a, long long b, long long &x, long long &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int z = x;
x = y;
y = z - y * (a / b);
return d;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++) {
scanf("%d %d", &a[i], &b[i]);
mod *= a[i];
}
for (int i = 1; i <= n; i ++) {
m = mod / a[i];
exgcd(m, a[i], x, y);
k = (a[i] + x % a[i]) % a[i];
ans = (ans + b[i] * k * m) % mod;
}
printf("%lld", ans);
return 0;
}