1.暴力大法
(时间复杂度为O(O(n)*sqrt(n))
#include<iostream>
#include<math.h>
using namespace std;
bool is_prime(int n)
{
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)return false;
}
return true;
}
signed main()
{
int n; cin >> n;
for (int i = 2; i <= n; i++)
{
if(is_prime(i))cout<<i<<" ";
}
return 0;
}
2.埃氏筛
(时间复杂度为O(n)*logn)
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
bool st[100010];
int p[100010];
int n,cnt;
void is_prime(int x)
{
for (int i = 2; i <= x; i++)
{
if (st[i])continue;
if (!st[i])
{
p[++cnt] = i;
for (int j = i; i * j <= n; j++)
{
st[i*j] = true;
}
}
}
}
signed main()
{
cin >> n;
is_prime(n);
for (int i = 2; i <= n; i++)
{
if (!st[i])cout << i << " ";
}
cout << endl;
cout << cnt<<endl;//质数数目
for (int i = 1; i <= cnt; i++)cout << p[i] << " ";//储存质数的数组
return 0;
}
3.欧拉筛(线性筛)
(时间复杂度可以至O(n)为最优筛法)
#include<iostream>
using namespace std;
const int N = 1000010;
int primes[N],n,cnt;
bool st[N];
void get_primes(int n)
{
for(int i = 2; i <= n; i ++ )
{
if(!st[i])
primes[cnt ++ ] = i;
for(int j = 0; primes[j] * i <= n; j ++ )
{
st[primes[j] * i] = true;
if(i % primes[j] == 0)
break;
}
}
}
int main()
{
cin>>n;
get_primes(n);
cout<<cnt;
return 0;
}
例
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e7 + 10;
vector<int> p;
int cnt = 0;
bool st[N];
void get_primes()
{
for (int i = 2; i <= 10000010; i++)
{
if (!st[i])
{
p.push_back(i);
cnt++;
}
for (int j = 0; p[j] * i <= 10000010; j++)
{
st[p[j] * i] = true;
if (i % p[j] == 0)
break;
}
}
}
signed main()
{
int t;
scanf("%d", &t);
get_primes();
while (t--)
{
int n;
scanf("%d", &n);
for (int i = 0; i < cnt; i++)
{
auto f = lower_bound(p.begin(), p.end(), n-p[i]);
if (n-p[i] == *f)
{
printf("%d %d\n", p[i], n - p[i]);
break;
}
else continue;
}
}
return 0;
}
经典の回文素数
https://vjudge.csgrandeur.cn/contest/568088#problem/B
#include <iostream>
#include <algorithm>
#include <cstring>
#include<cmath>
using namespace std;
bool book[10000001];
void prime(int b)
{
memset(book, true, sizeof(book));
book[1] = false;
int n = sqrt(b);
for (int i = 2; i <= n; i++)
{
if (book[i])
{
for (int j = 2; j <= b / i; j++)
book[i * j] = false;
}
}
}
bool palindrome(int n)
{
int x = 0;
int m = n;
while (m > 0)
{
x = x * 10 + m % 10;
m = m / 10;
}
if (x == n)
return true;
else
return false;
}
int main()
{
int a, b;
cin >> a >> b;
if (b >= 10000000)
b = 9999999;
int n = a;
prime(b);
for (int n = a; n <= b; n++)
{
if (book[n] && palindrome(n))
{
cout << n << endl;
}
}
return 0;
}
寻找素数对
https://vjudge.csgrandeur.cn/contest/568088#problem/C
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e7 + 10;
vector<int> p;
int cnt = 0;
bool st[N];
int n;
void get_primes()
{
for (int i = 2; i <= 10010; i++)
{
if (!st[i])
{
p.push_back(i);
cnt++;
}
for (int j = 0; p[j] * i <= 10010; j++)
{
st[p[j] * i] = true;
if (i % p[j] == 0)
break;
}
}
}
int dfs(int x,int y)
{
if(p[x]+p[y]==n)
{
return x;
}
if(p[x]+p[y]>n)return dfs(x,y-1);
if(p[x]+p[y]<n)return dfs(x+1,y);
}
signed main()
{
get_primes();
while (cin>>n)
{
int ans=0;
for (int i = 0; i < cnt; i++)
{
if(p[i]>n)
{
ans=i;
break;
}
}
for(int i=0;i<ans;i++)
{
if(p[i]==n/2)
{
cout<<p[i]<<" "<<p[i]<<endl;
break;
}
if(p[i]>n/2)
{
int x=dfs(i-1,i);
if(p[x]<n-p[x])cout<<p[x]<<" "<<n-p[x]<<endl;
else cout<<n-p[x]<<" "<<p[x]<<endl;
break;
}
}
}
return 0;
}
https://vjudge.csgrandeur.cn/contest/568088#problem/F
取余大法+2^类升幂,大大减小时间复杂度
#include<iostream>
#include<cmath>
using namespace std;
long long ModExp(long long a, long long b, long long n)
{
long long tmp = a;
long long res = 1;
while (b)
{
if (b & 1)
res = res * tmp % n;
tmp = tmp * tmp % n;
b >>= 1;
}
return res;
}
bool is_prime(int n)
{
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
return false;
}
return true;
}
int main()
{
long long p, a;
while (cin >> p >> a )
{
if(p==0&&a==0)break;
if (is_prime(p))
{
cout << "no" << endl;
continue;
}
else
{
if (ModExp(a, p, p) == a)
cout << "yes" << endl;
else
cout << "no" << endl;
}
}
}
三素数相加
https://vjudge.csgrandeur.cn/contest/568088#problem/H
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e7 + 10;
vector<int> p;
int cnt = 0;
bool st[N];
int n;
bool s[10010];
void get_primes()
{
for (int i = 2; i <= 10010; i++)
{
if (!st[i])
{
p.push_back(i);
cnt++;
}
for (int j = 0; p[j] * i <= 10010; j++)
{
st[p[j] * i] = true;
if (i % p[j] == 0)
break;
}
}
}
int main()
{
int t, i, j, m;
get_primes();
while (~scanf("%d", &t))
{
int ans = 0,num=0;
for (int i = 0; i < cnt; i++)
{
if (p[i] > t)
{
ans = i;
break;
}
s[p[i]] = true;
}
//cout << p[0] << endl;
for (i = 0; i < ans; i++)
{
for (j = i; j < ans; j++)
{
m = t - p[i] - p[j];
if (m < 0)
{
break;
}
if (s[m] && m >= p[j])
num++;
}
}
cout << num << endl;
}
return 0;
}
#include<iostream>
int a[1000010], b[1000001];
using namespace std;
signed main()
{
a[0] = 1;
a[1] = 1;
int k = 1;
for (int i = 2; i < 1000010; i++)
{
if (a[i] == 0)
{
b[i] = k++;
for (int j = i; j < 1000010; j = j + i)
a[j] = i;
}
}
b[1] = 0;
int n, sum;
while (~scanf("%d", &n))
{
printf("%d\n", b[a[n]]);
}
return 0;
}
4.GCD,LCM(最大公因数,最小公倍数)
gcd
int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; }
lcm
int lcm(int a,int b) { return a*b/gcd(a,b); }
例题
#include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; } signed main() { ll T; cin >> T; while (T--) { ll m, n; cin >> m >> n; if (gcd(m, n) == 1) cout << "NO" << endl; else cout<<"YES"<<endl; } return 0; }
#include<stdio.h>
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
int p, q;
while (scanf("%d %d", &p, &q) != EOF)
printf("%d\n", p + q - gcd(p, q));
return 0;
}
如下是一个蛋糕,我的理解是,首先要均分p份,那就先切p份,因为还要能平均分为q份,那么应该再切q刀,但是要求最小切的次数,那么应该尽量找到能重合的边来切,而重合的边数即为两个数的最大公因数