1. 程式人生 > 實用技巧 >數論題單

數論題單

Kuangbin題單

Kuangbin題單好像有點水,先做別的題去

A - Bi-shoe and Phi-shoe

Φ (n)表示長度為小於數字n的和n互質的數的個數,也就是尤拉函式。現在給出n個幸運數字,對於每一個幸運數字,要求的x,使Φ (n)的值大於等於這個幸運數字,求這些x和的最小值。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
int prime[maxn], cnt;
int vis[maxn];
void get(int N) {
	for (int i = 2; i < N; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
		}
		for (int j = 1; j <= cnt && prime[j] * i < N; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0)break;
		}
	}
}
int T, n;
int main() {
	get(maxn);
	scanf("%d", &T);
	for (int cs = 1; cs <= T;cs++) {
		scanf("%d", &n);
		long long ans = 0;
		while (n--) {
			int x; scanf("%d", &x);
			ans += *lower_bound(prime + 1, prime + 1 + cnt, x + 1);
		}
		printf("Case %d: %lld Xukha\n", cs, ans);
	}
}

F - Goldbach`s Conjecture

U - Primes

阿星在入門數論學習之前,她選擇從研究素數入手。她想請你幫忙寫一個程式判斷某個數字是否為素數。如果一個數n只能被1和n整除,則數n為素數。但阿星她不喜歡2這個數字,所以她不認為2是素數。所以你的程式在判斷素數的時候,如果是2,不能判斷成2為素數

注意結束條件不是 n == 0

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
int prime[maxn], cnt;
int vis[maxn];
void get(int N) {
	for (int i = 2; i < N; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
		}
		for (int j = 1; j <= cnt && prime[j] * i < N; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0)break;
		}
	}
}
int T, n;
int main() {
	get(maxn); int cs = 0; vis[1] = vis[2] = 1;
	while (scanf("%d", &n) && n > 0) {
		printf("%d: %s\n", ++cs, vis[n] ? "no" : "yes");
	}
}

其他地方的題

杜教篩

洛谷模板(杜教篩)

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

template<typename T>void read(T& x) {
	x = 0;
	int p = 1;
	char c = getchar();	
	while (!isdigit(c)) { if (c == '-')p = -1, c = getchar(); }
	while (isdigit(c)) { x = (x << 1) + (x << 3) + (c - 48); c = getchar(); }
	x *= p;
}

template<typename T>void write(T x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

typedef long long ll;
const int maxn = 6e6 + 10;
int mu[maxn];
ll phi[maxn];
int sum_mu[maxn];
ll sum_phi[maxn];
int vis[maxn];
int prime[maxn], cnt;
unordered_map<int, ll>MU, PHI;

void get(int N) {
	phi[1] = mu[1] = 1;
	for (int i = 2; i <= N; i++) {
		if (!vis[i]) {
			prime[++cnt] = i;
			mu[i] = -1;
			phi[i] = i - 1;
		}
		for (int j = 1; j <= cnt && prime[j] * i <= N; j++) {
			vis[prime[j] * i] = 1;
			if (i % prime[j] == 0) {
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			else {
				mu[i * prime[j]] = mu[i] * -1;
				phi[i * prime[j]] = phi[i] * (prime[j] - 1);
			}
		}
	}
	for (int i = 1; i <= N; i++) {
		sum_phi[i] = sum_phi[i - 1] + phi[i];
		sum_mu[i] = sum_mu[i - 1] + mu[i];
	}
}
ll djs_mu(ll x) {
	if (x <= maxn - 10)return sum_mu[x];
	if (MU.count(x) != 0)return MU[x];
	int ans = 1;
	for (int l = 2, r;l <= x; l = r + 1) {
		r = x / (x / l);
		ans -= (r - l + 1) * djs_mu(x / l);
	}
	return MU[x] = ans;
}

ll djs_phi(ll x) {
	if (x <= maxn - 10)return sum_phi[x];
	if (PHI.count(x) != 0)return PHI[x];
	ll ans = x * (x + 1) / 2;
	for (ll l = 2, r; l <= x; l = r + 1) {
		r = x / (x / l);
		ans -= (r - l + 1) * djs_phi(x / l);
	}
	return PHI[x] = ans;
}

int main() {
	int t, n;
	read(t);
	get(maxn - 10);
	while (t--) {
		read(n);
		write(djs_phi(n)); putchar(' ');
		write(djs_mu(n)); puts("");
	}
}

莫比烏斯反演

約數和

YY的GCD