其他分享
首页 > 其他分享> > 数论做题记录

数论做题记录

作者:互联网

P3811 【模板】乘法逆元

数据范围是只能 \(\mathcal{O}(n)\) 过的。

考虑递推逆元。

设 \(t = p / i, k = p % i\)。

\(t * i + k \equiv 0(\bmod p)\).

\(k \equiv - t * i (\bmod p)\)

\(inv[i] \equiv - t * inv[k] (\bmod p)\)

\(inv[i] \equiv - p / i * inv[p % i] (\bmod p)\)。

注意可能出现负数,所以加上个 \(p\)。

/**
 *	author: TLE_Automation
 *	creater: 2022.8.22
 *  say: xpp 什么时候找到 npy 捏
**/
#include<cmath>
#include<queue>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc getchar 
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int MAXN = 2e3 + 10;
const int Maxn = 2e5 + 10;
const int mod = 998244353;
const ll inf = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) {return !b ? a : gcd(b, a % b);}
inline void print(int x) {if (x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0');}
inline int ksm(int a, int b) {int base = a % mod, res = 1; while(b){if(b & 1) res = (res * base) % mod; base = (base * base) % mod, b >>= 1;}return res % mod;}
inline int mul(int a, int b) {int base = a % mod, res = 0; while(b){if(b & 1) res = (res + base) % mod; base = (base + base) % mod, b >>= 1;}return res % mod;}
inline char readchar() {static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;}
inline int read() { int res = 0, f = 0; char ch = gc();for (; !isdigit(ch); ch = gc()) f |= (ch == '-'); for (; isdigit(ch); ch = gc()) res = (res << 1) + (res << 3) + (ch ^ '0'); return f ? -res : res;}

ll inv[N << 2], n, p;
/*
	t = p / i, k = p % i
	t * i + k % p = 0
	k \equiv -t * i (mod p)
	inv[i] \equiv -t * inv[k] (mod p)
	inv[i] \equiv - (p / i) * inv[p % i] (mod p)
	inv[i] \equiv p - (p / i) * inv[p % i] (mod p)
*/

signed main() 
{
	n = read(), p = read();
	inv[1] = 1;
	for(int i = 2; i <= n; i++) inv[i] = ((p  - (p / i) * inv[p % i]) % p + p) % p;
	for(int i = 1; i <= n; i++) printf("%lld\n", inv[i]);
	return (0 - 0);
}

P1349 广义斐波那契数列

简单矩乘。

直接推就行了。

/**
 *	author: TLE_Automation
 *	creater: 2022.8.23
**/
#include<cmath>
#include<queue>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc getchar 
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 998244353;
const ll inf = 0x3f3f3f3f3f3f3f3f;
#define debug cout << "i ak ioi" << "\n"
inline void print(int x) {if (x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0');}
inline char readchar() {static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;}
inline int read() { int res = 0, f = 0; char ch = gc();for (; !isdigit(ch); ch = gc()) f |= (ch == '-'); for (; isdigit(ch); ch = gc()) res = (res << 1) + (res << 3) + (ch ^ '0'); return f ? -res : res;}

int p, q, a1, a2, n, m;

struct Mariax {
	int a[5][5];
	Mariax() {memset(a, 0, sizeof a);}
	friend Mariax operator * (Mariax x, Mariax y) {
		Mariax res; 
		for(int i = 1; i <= 2; i++) 
			for(int j = 1; j <= 2; j++) 
				for(int k = 1; k <= 2; k++) 
					res.a[i][j] = (res.a[i][j] + (x.a[i][k] * y.a[k][j]) % m) % m;		
		return res;
	}
}Base, A;

Mariax ksm(Mariax B, int k) {
	Mariax res;
	for(int i = 1; i <= 2; i++) res.a[i][i] = 1;
	while(k) {
		if(k & 1) res = (res * B);
		B = (B * B), k >>= 1;
	}
	return res;
}

signed main() 	
{
	p = read(), q = read(), a1 = read(), a2 = read(), n = read(), m = read();
	A.a[1][1] = a2, A.a[1][2] = a1;
	Base.a[1][1] = p, Base.a[1][2] = 1, Base.a[2][1] = q, Base.a[2][2] = 0;
	if(n == 1) return printf("%lld\n", a1 % m), 0;
	else if(n == 2) return printf("%lld\n", a2 % m), 0;
	A = A * ksm(Base, n - 1);
	printf("%lld\n", A.a[1][2] % m);
 	return (0 - 0);
}

/**
 * _ooOoo_
 * o8888888o
 * 88" . "88
 * (| -_- |)
 *  O\ = /O
 * ___/`---'\____
 * .   ' \\| |// `.
 * / \\||| : |||// \
 * / _||||| -:- |||||- \
 * | | \\\ - /// | |
 * | \_| ''\---/'' | |
 * \ .-\__ `-` ___/-. /
 * ___`. .' /--.--\ `. . __
 * ."" '< `.___\_<|>_/___.' >'"".
 * | | : `- \`.;`\ _ /`;.`/ - ` : | |
 * \ \ `-. \_ __\ /__ _/ .-` / /
 * ======`-.____`-.___\_____/___.-`____.-'======
 * `=---='
 *  .............................................
 *        佛曰:bug泛滥,我已瘫痪!
 */

P2421 [NOI2002] 荒岛野人

\(C_i + x P_i \equiv C_j + x P_j (\bmod M)\)。

\(x (P_i - P_j) \equiv C_j - C_i (\bmod M)\)。

\(x (P_i - P_j) = c_j - C_i + My\)。

\(x(P_i - P_j) - My = C_j - C_i\)

这个式子形如 \(ax + by = c\),可以用 exgcd 求解,发现 \(n \le 15, M \le 1e6\)。

考虑枚举 \(M\),exgcd 判断是否有解,如果有解的判断该解是否可行,指的是如果有解但是这俩个人相遇之前有一个人噶了。

/**
 *	author: TLE_Automation
 *	creater: 2022.8.22
 *      say: xpp 什么时候找到 npy 捏
**/
#include<cmath>
#include<queue>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc getchar 
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int MAXN = 2e3 + 10;
const int Maxn = 2e5 + 10;
const int mod = 998244353;
const ll inf = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) {return !b ? a : gcd(b, a % b);}
inline void print(int x) {if (x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0');}
inline int ksm(int a, int b) {int base = a % mod, res = 1; while(b){if(b & 1) res = (res * base) % mod; base = (base * base) % mod, b >>= 1;}return res % mod;}
inline int mul(int a, int b) {int base = a % mod, res = 0; while(b){if(b & 1) res = (res + base) % mod; base = (base + base) % mod, b >>= 1;}return res % mod;}
inline char readchar() {static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;}
inline int read() { int res = 0, f = 0; char ch = gc();for (; !isdigit(ch); ch = gc()) f |= (ch == '-'); for (; isdigit(ch); ch = gc()) res = (res << 1) + (res << 3) + (ch ^ '0'); return f ? -res : res;}

int n, p[20], c[20], l[20];
int x, y, Max;
int exgcd(int a, int b, int &x, int &y) {
	if(!b) {x = 1, y = 0; return a;}
	int res = exgcd(b, a % b, x, y);
	int tmp = x; x = y, y = tmp - (a / b) * y;
	return res;
}

bool Check(int M) {
	for(int i = 1; i <= n; i++) {
		for(int j = i + 1; j <= n; j++) {
			int a = p[i] - p[j], b = M, C = c[j] - c[i];
			int Gcd = exgcd(a, b, x, y);
			if(C % Gcd) continue;
			a /= Gcd, b /= Gcd, C /= Gcd; b = abs(b);
			x = (x  * C % b + b) % b;
			if(x <= l[i] && x <= l[j]) return false;
		}
	}
	return 1;
}

signed main() 
{
	n = read();
	for(int i = 1; i <= n; i++)
		c[i] = read(), p[i] = read(), l[i] = read(), Max = std::max(Max, c[i]);
	for(int i = Max; ; i++) if(Check(i)) return printf("%d\n", i), 0; 
	return (0 - 0);
}

P3868 [TJOI2009] 猜数字

\(b_i \mid (n - a_i)\)

\(n - a_i \equiv 0 (\bmod b_i)\)

\(n \equiv a_i (\bmod b_i)\)

然后就是 CRT 的板子了。

/**
 *	author: TLE_Automation
 *	creater: 2022.8.24
**/
#include<cmath>
#include<queue>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc getchar 
#define INF 0x3f3f3f3f
#define int long long 
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 998244353;
const ll inf = 0x3f3f3f3f3f3f3f3f;
#define debug cout << "i ak ioi" << "\n"
inline void print(int x) {if (x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0');}
inline char readchar() {static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;}
inline int read() { int res = 0, f = 0; char ch = gc();for (; !isdigit(ch); ch = gc()) f |= (ch == '-'); for (; isdigit(ch); ch = gc()) res = (res << 1) + (res << 3) + (ch ^ '0'); return f ? -res : res;}

int n, a[N], b[N], M = 1, x, y, ans = 0;

int exgcd(int a, int b, int &x, int &y) {
	if(!b) {x = 1, y = 1; return a; }
	int res = exgcd(b, a % b, x, y);
	int tmp = x; x = y, y = tmp - (a / b) * y;
	return res;
}

inline int mul(int a, int b, int p) {
	int res = 0;
	while(b) {
		if(b & 1) res = (res + a) % p;
		a = (a + a) % p, b >>= 1;
	} return res;
}

signed main() 	
{
	n = read();
	for(int i = 1; i <= n; i++) a[i] = read();
	for(int i = 1; i <= n; i++) b[i] = read(), M *= b[i];
	for(int i = 1; i <= n; i++) a[i] = (a[i] + b[i]) % b[i];
	for(int i = 1; i <= n; i++) {
		int M_i = M / b[i];
		exgcd(M_i, b[i], x, y);
		x = (x + b[i]) % b[i];
		ans = (ans + (mul(mul(M_i, x, M), a[i], M) + M) % M + M) % M;
	}
	printf("%lld\n", ans);
	return (0 - 0); 
}

/**
 * _ooOoo_
 * o8888888o
 * 88" . "88
 * (| -_- |)
 *  O\ = /O
 * ___/`---'\____
 * .   ' \\| |// `.
 * / \\||| : |||// \
 * / _||||| -:- |||||- \
 * | | \\\ - /// | |
 * | \_| ''\---/'' | |
 * \ .-\__ `-` ___/-. /
 * ___`. .' /--.--\ `. . __
 * ."" '< `.___\_<|>_/___.' >'"".
 * | | : `- \`.;`\ _ /`;.`/ - ` : | |
 * \ \ `-. \_ __\ /__ _/ .-` / /
 * ======`-.____`-.___\_____/___.-`____.-'======
 * `=---='
 *          .............................................
 *           佛曰:bug泛滥,我已瘫痪!
 */

标签:ch,记录,数论,res,int,base,include,mod
来源: https://www.cnblogs.com/tttttttle/p/16625538.html