算法竞赛入门经典(第二版)-刘汝佳-第十章 数学概念与方法 习题(12/51)

文章目录

  • 说明
  • 习题
    • 习10-1
    • 习10-2
    • 习10-3
    • 习10-4
    • 习10-5
    • 习10-6
    • 习10-7
    • 习10-8
    • 习10-9
    • 习10-10
    • 习10-11
    • 习10-12
    • 习10-13
    • 习10-14
    • 习10-15
    • 习10-16
    • 习10-17
    • 习10-18
    • 习10-19
    • 习10-20
    • 习10-21
    • 习10-22
    • 习10-23
    • 习10-24
    • 习10-25
    • 习10-26
    • 习10-27
    • 习10-28
    • 习10-29
    • 习10-30
    • 习10-31
    • 习10-32
    • 习10-33
    • 习10-34
    • 习10-35
    • 习10-36
    • 习10-37
    • 习10-38
    • 习10-39
    • 习10-40
    • 习10-41
    • 习10-42
    • 习10-43
    • 习10-44
    • 习10-45
    • 习10-46
    • 习10-47
    • 习10-48
    • 习10-49
    • 习10-50
    • 习10-51

说明

本文是我对第十章51道习题的练习总结,建议配合紫书——《算法竞赛入门经典(第2版)》阅读本文。
先贴代码,文字性题解回头再补充。

习题

习10-1

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAX = 100;

int A[10][10];

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	int T;
	cin >> T;
	FOR1(t, 1, T) {
		FOR1(i, 0, 8) {
			if (i & 1) continue;
			FOR1(j, 0, i) {
				if (j & 1) continue;
				cin >> A[i][j];
			}
		}

		FOR1(i, 0, 6) {
			if (i & 1) continue;
			FOR1(j, 0, i) {
				if (j & 1) continue;
				A[i + 2][j + 1] = (A[i][j] - A[i + 2][j] - A[i + 2][j + 2]) / 2;
				A[i + 1][j] = A[i + 2][j] + A[i + 2][j + 1];
				A[i + 1][j + 1] = A[i + 2][j + 1] + A[i + 2][j + 2];
			}
		}

		FOR1(i, 0, 8) {
			FOR1(j, 0, i-1) {
				printf("%d ", A[i][j]);
			}
			printf("%d\n", A[i][i]);
		}
	}
	return 0;
}

习10-2

题意

思路

代码



习10-3

题意

思路

代码



习10-4

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAX = 1299709+100000;//确保下一个素数被包含

int n;
int isprime[MAX];
vector prime;

void process_prime() {
	memset(isprime, 0x3f, sizeof(isprime));
	isprime[1] = 0;
	FOR1(i, 2, MAX) {
		if (isprime[i]) {
			prime.push_back(i);
			for (int j = i * 2; j <= MAX; j += i) {
				isprime[j] = 0;
			}
		}
	}
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	while (cin >> n && n) {
		if (isprime[n]) {
			printf("0\n", n);
			continue;
		}
		int s = prime.size();
		FOR1(i, 0, s - 1) {
			if (prime[i] > n) {
				printf("%d\n", prime[i] - prime[i - 1]);
				break;
			}
		}
	}
	return 0;
}

习10-5

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAXN = 1120;
const int MAXP = 187; //计算得出最多有187个素数
const int MAXK = 14; //计算得出最多有187个素数

int n, k, ans;
int isprime[MAXN+1];
vector prime;
//int dp[MAXP + 1][MAXK + 1][MAXN + 1]; //dp[i][j][m]表示前i个素数中挑出j个素数其值为m的可能数,实际上第一维可以省略
int dp[MAXK + 1][MAXN + 1]; //dp[j][m]表示前i个素数中挑出j个素数其值为m的可能数,第一维已经省略

void process_prime() {
	memset(isprime, 0x3f, sizeof(isprime));
	isprime[1] = 0;
	FOR1(i, 2, MAXN) {
		if (isprime[i]) {
			prime.push_back(i);
			for (int j = i * 2; j <= MAXN; j += i) {
				isprime[j] = 0;
			}
		}
	}
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	while (cin >> n >> k && n) {
		memset(dp, 0, sizeof(dp));
		dp[0][0] = 1;
		FOR1(i, 1, MAXP) {
			if (prime[i-1] > n) break;
			int pi = prime[i-1];
			FOR2(j, min(i, k), 1) {
				FOR2(m, n, pi) {
					dp[j][m] += dp[j - 1][m - pi];
				}
			}
		}
		printf("%d\n", dp[k][n]);
	}
	return 0;
}

习10-6

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAX = 10000;//确保下一个素数被包含

int n, p; //p表示prime中素数个数
int isprime[MAX + 1];
vector prime;

void process_prime() {
	memset(isprime, 0x3f, sizeof(isprime));
	isprime[1] = 0;
	FOR1(i, 2, MAX) {
		if (isprime[i]) {
			prime.push_back(i);
			for (int j = i * 2; j <= MAX; j += i) {
				isprime[j] = 0;
			}
		}
	}
	p = prime.size();
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	while (cin >> n && n) {
		int res = 0;
		int i = 0, j = 0;
		int s = prime[0];
		while (j < p) {
			if (s == n)	{
				res++;
				if (j == p - 1) break;
				s += prime[++j];
			}
			else if (s < n) {
				if (j == p - 1) break;
				s += prime[++j];
			}
			else {
				if (i == p - 1) break;
				s -= prime[i++];
				if (i > j)
					s += prime[++j];
			}
		}
		printf("%d\n", res);
	}
	return 0;
}

习10-7

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef long long LL;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const LL MAX = 1000000;
const LL LMAX = MAX*MAX;

LL a[2];
int p; //p表示oneprime中素数个数
int isprime[MAX + 1];
vector oneprime;

void process_prime() {
	memset(isprime, 0x3f, sizeof(isprime));
	isprime[1] = 0;
	FOR1(i, 2, MAX) {
		if (isprime[i]) {
			for (LL j = (LL)i * i; j <= LMAX; j *= i)
				oneprime.push_back(j);
			for (int j = i * 2; j <= MAX; j += i) {
				isprime[j] = 0;
			}
		}
	}
	sort(oneprime.begin(), oneprime.end());
	p = oneprime.size();
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	int T;
	cin >> T;
	FOR1(t, 1, T) {
		cin >> a[0] >> a[1];
		a[1]++;
		int res[2];
		FOR1(j, 0, 1) {
			FOR1(i, 0, p - 1) {
				if (oneprime[i] >= a[j]) {
					res[j] = i;
					break;
				}
			}
		}
		printf("%d\n", res[1] - res[0]);
	}
	return 0;
}

习10-8

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef long long LL;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const LL MAX = 500000;
const LL LMAX = MAX*MAX;

int n, n0;
map oneprime;

void process_prime() {
	FOR1(i, 2, MAX) {
		if (!oneprime.count(i)) {
			int k = 2;
			for (LL j = (LL)i * i; j <= LMAX; j *= i, k++)
			if (!oneprime.count(j)) oneprime[j] = k;
		}
	}
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	while (cin >> n && n) {
		if (n == (-(1<<30) - (1<<30))) {
			printf("31\n");
			continue;
		}
		n0 = abs(n);
		if (oneprime.count(n0)) {
			int ans = oneprime[n0];
			if (n < 0) {
				while (ans % 2 == 0) ans >>= 1;
			}
			printf("%d\n", ans);
		}
		else
			printf("1\n");
	}
	return 0;
}

习10-9

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

//const int MAXN2 = 1e9;
const int MAXN = 40000;

int L, U;
int isprime[MAXN+1];
vector prime;
int resn, resi;

void process_prime() {
	memset(isprime, 0x3f, sizeof(isprime));
	isprime[1] = 0;
	FOR1(i, 2, MAXN) {
		if (isprime[i]) {
			prime.push_back(i);
			for (int j = i * 2; j <= MAXN; j += i) {
				isprime[j] = 0;
			}
		}
	}
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	process_prime();
	int T;
	cin >> T;
	FOR1(t, 1, T) {
		cin >> L >> U;
		resn = L, resi = 0;
		FOR1(k, L, U) {
			int k1 = k;
			int ik = k1 - L;
			int res = 1;
			int k2 = sqrt(k1) + 1;
			int pcnt = prime.size();
			FOR1(j, 0, pcnt-1) {
				int mult = 1;
				int pj = prime[j];
				if (k1 == 1) break;
				while (k1 % pj == 0) {
					k1 /= pj;
					mult++;
				}
				res *= mult;
			}
			if (k1 > 1) //说明还有约数
				res *= 2;
			if (res > resi) {
				resn = k;
				resi = res;
			}
		}
		printf("Between %d and %d, %d has a maximum of %d divisors.\n", L, U, resn, resi);
	}
	return 0;
}

习10-10

题意

思路

代码



习10-11

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAXN = 10000;

int n;
string s[3];

string add(string s1, string s2) {
	string sum;
	int up = 0;
	int l1 = s1.size(), l2 = s2.size();
	FOR1(i, 0, MAXN) {
		if (i >= l1 && i >= l2) {
			if (up) sum += (char)(up + 48);
			break;
		}
		int a1 = (i < l1) ? s1[i]-48 : 0;
		int a2 = (i < l2) ? s2[i]-48 : 0;
		up = up + a1 + a2;
		sum += (char)(up % 10 + 48);
		up /= 10;
	}
	return sum;
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	while (cin >> n) {
		s[1] = "1";
		s[2] = "2";
		FOR1(i, 0, n - 3) {
			s[0] = s[1];
			s[1] = s[2];
			s[2] = add(s[0], s[1]);
		}
		s[1] = add(s[0], s[2]);
		int scnt = s[1].size();
		FOR2(i, scnt - 1, 0)
			printf("%c", s[1][i]);
		printf("\n");
	}
	return 0;
}

习10-12

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAXN = 50000;

int n;
double F[MAXN + 1];

void pre_process() {
	F[1] = 1;
	F[2] = 0.5;
	FOR1(i, 2, MAXN - 1)
		F[i + 1] = F[i] * (2 * i - 1) / 2 / i;
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	pre_process();
	int T;
	cin >> T;
	FOR1(t, 1, T) {
		cin >> n;
		printf("%.4lf\n", 1 - F[n / 2]);
	}
	return 0;
}

习10-13

题意

思路

代码



习10-14

题意

思路

代码



习10-15

题意

思路

代码



习10-16

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAXN = 1000;

int n;
string S[1001];

string add(string s1, string s2) {
	string sum;
	int up = 0;
	int l1 = s1.size(), l2 = s2.size();
	FOR1(i, 0, MAXN) {
		if (i >= l1 && i >= l2) {
			if (up) sum += (char)(up + 48);
			break;
		}
		int a1 = (i < l1) ? s1[i] - 48 : 0;
		int a2 = (i < l2) ? s2[i] - 48 : 0;
		up = up + a1 + a2;
		sum += (char)(up % 10 + 48);
		up /= 10;
	}
	return sum;
}

void pre_process() {
	S[1] = "0";
	S[2] = "1";
	S[3] = "1";
	FOR1(i, 4, MAXN)
		S[i] = add(S[i-2], add(S[i-1], S[i-2]));
}

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	pre_process();
	while (cin >> n) {
		int scnt = S[n].size();
		FOR2(i, scnt - 1, 0)
			printf("%c", S[n][i]);
		printf("\n");
	}
	return 0;
}

习10-17

题意

思路

代码


#include 
#include 
#include 
using namespace std;
    
const int N = 1000001;

bool isPrime[N+1];
bool isSemi[N+1];
int countSemi[N/4+1];
    
void initPrime()
{   
    int i;
    for (i = 0; i <= N; i ++)
        isPrime[i] = true;
    isPrime[0] = isPrime[1] = false;
    for (i = 5; i <= N; i += 4) {
        if (isPrime[i]) {
            if (i > (int)sqrt((double)N)) continue;
            for (int j = i*i; j <= N; j += 4*i)
                isPrime[j] = false;
        }
    }
}

void initSemi()
{
    int i, j;
    for (i = 1; i <= N; i += 4) {
        isSemi[i] = false;
        countSemi[i/4] = 0;
    }
    for (i = 5; i <= N; i += 4) {
        if (i > (int)sqrt((double)N)) break;
        for (j = i; j <= N; j += 4) {
            if (i * j > N) break;
            if (isPrime[i] && isPrime[j])
                isSemi[i * j] = true;
        }
    }
    for (i = 5; i <= N; i += 4) {
        countSemi[i/4] = countSemi[i/4-1];
        if (isSemi[i])
            countSemi[i/4] ++;
    }
}

int main(void)
{
    int n;
    initPrime();
    initSemi();
    while (cin >> n && n) {
        printf("%d %d\n", n, countSemi[n/4]);
    }
    return 0;
}

习10-18

题意

思路

代码



习10-19

题意

思路

代码



习10-20

题意

思路

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define FOR1(i, a, b) for (int i = (a); i <= (int)(b); i++)
#define FOR2(i, a, b) for (int i = (a); i >= (int)(b); i--)

const int MAXM = 2000;

int n, m;
int u[MAXM], d[MAXM];

int main() {
#ifdef CODE_LIANG
	freopen("datain.txt", "r", stdin);
	freopen("dataout.txt", "w", stdout);
#endif
	while (cin >> n >> m) {
		int ans = -1, minfloor = 0x3f3f3f3f;
		FOR1(i, 0, m - 1) {
			cin >> u[i] >> d[i];
			int floor = (n*u[i]) - (n*u[i] - 1) / (u[i] + d[i]) * (u[i] + d[i]);
			if (floor < minfloor) {
				ans = i;
				minfloor = floor;
			}
		}
		printf("%d\n", minfloor);
	}
	return 0;
}

习10-21

题意

思路

代码



习10-22

题意

思路

代码



习10-23

题意

思路

代码



习10-24

题意

思路

代码



习10-25

题意

思路

代码



习10-26

题意

思路

代码



习10-27

题意

思路

代码



习10-28

题意

思路

代码



习10-29

题意

思路

代码



习10-30

题意

思路

代码



习10-31

题意

思路

代码



习10-32

题意

思路

代码



习10-33

题意

思路

代码



习10-34

题意

思路

代码



习10-35

题意

思路

代码



习10-36

题意

思路

代码



习10-37

题意

思路

代码



习10-38

题意

思路

代码



习10-39

题意

思路

代码



习10-40

题意

思路

代码



习10-41

题意

思路

代码



习10-42

题意

思路

代码



习10-43

题意

思路

代码



习10-44

题意

思路

代码



习10-45

题意

思路

代码



习10-46

题意

思路

代码



习10-47

题意

思路

代码



习10-48

题意

思路

代码



习10-49

题意

思路

代码



习10-50

题意

思路

代码



习10-51

题意

思路

代码



你可能感兴趣的:(算法竞赛入门经典)