数学知识
exgcd
对于 $\mathrm{ax+by=(a,b)}$ 的方程必然有解 $\mathrm{(x,y)}$.
$\mathrm{b=0}$ 时解为 $\mathrm{(1,0)}$.
$\mathrm{b}$ 不等于 $\mathrm{0}$ 时考虑递归求解.
考虑求出 $\mathrm{(b,a \mod b)}$ 时的解 $\mathrm{(x[2], y[2])}$ 则 $\mathrm{(x[1], y[1])}$ 为:
$\mathrm{x[1]=y[2]}$, $\mathrm{y[1]=x[2]-(a/b) \times y[2]}$.
若想求 $\mathrm{ax+by=c}$, 则 $\mathrm{c}$ 要整除 $\mathrm{(a,b)}$.
$\mathrm{x}$ 乘上 $\mathrm{c/(a,b)}$ 即为一个解,通解增量为 $\mathrm{b/(a,b)}$.
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) { x = 1, y = 0; return a; } ll gc = exgcd(b, a % b, x, y); // 得到一组 x, y ll t = x; x = y; y = t - (a / b) * y; return gc; } int main() { // setIO("input"); ll a, b, x0, y0; scanf("%lld%lld", &a, &b); ll gcd = exgcd(a, b, x0, y0); ll mod = b / gcd; printf("%lld", (x0 % mod + mod) % mod); return 0; }
青蛙的约会
来源:luoguP1516
推一下式子,是 $\mathrm{exgcd}$ 的形式,然后求出最小解即可.
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #define ll long long #define pb push_back #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll exgcd(ll a, ll b, ll &x, ll &y){ if(!b) { x = 1, y = 0; return a; } ll gc = exgcd(b, a % b, x, y); ll t = x; x = y, y = t - (a / b) * y; return gc; } int main() { // setIO("input"); ll x, y, m, n, L, x0, y0; scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &L); ll a = m - n, b = L, c = y - x; ll gcd = exgcd(a, b, x0, y0); if(c % gcd) { printf("Impossible"); } else { x0 *= (c / gcd); ll mod = abs(b / gcd); printf("%lld", (x0 % mod + mod) % mod); } return 0; }
线性筛
核心思想是用每个合数最小的质因数将其筛掉.
如果 $\mathrm{i \mod p=0}$ 则说明 $\mathrm{p}$ 后面的质数都不是最小的质数.