PAT 甲级 总结 —— 初级篇
一、数学类
常作为PAT中基本20分的小题,题目变化较为新颖,但基本思路不变。
1.1 素数
埃式筛选法:要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
int flag[maxn] = {
false};
int prime[maxn], pNum = 0;
void findprime(int n)
{
flag[0] = flag[1] = true;
for (int i = 2; i <= n; i++)
{
if (!flag[i])
{
prime[pNum++] = i;
for (int j = i*i; j <= n; j+=i)
{
flag[j] = true;
}
}
}
}
欧拉筛法:在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。
int flag[maxn] = {
false};
int prime[maxn];
void eulerSieve(int n)
{
fill(flag, flag + maxn, 0);
flag[0] = flag[1] = true;
fill(prime, prime + maxn, 0);
for (int i = 2; i <= maxn; i++) {
if (!flag[i]) {
prime[++prime[0]] = i;
}
for (int j = 1; j <= prime[0] && i * prime[j] <= maxn; j++) {
flag[i * prime[j]] = true;
if (i % prime[j] == 0) {
break;
}
}
}
}
[注]:
1、这里不是用 i 的倍数来消去合数,而是把 prime 里面纪录的素数,升序来当做要消去合数的最小素因子
2、对于 i%prime[j] == 0 就break的解释 :
当 i 是prime[j]的倍数时,i = k*prime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k * prime[j+1],
这里prime[j]是最小的素因子,当 i = k * prime[j+1] 时会重复,所以才跳出循环。
1.2 最大公约数
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
[注]:a>0, b>0
1.3 快速幂
long long ksm(long long a, int b)
{
long long base = a, ans = 1;
while (b != 0) {
<