(1)常规方法
注意一下 i*i<=n
以及,2 是最小的质数 1不是质数
(2)
埃氏筛法
参考网站。。。
就是如果这个是质数,把他们的所有倍数都删了。
比如2,4 6 8.。。。。
【直接能用的模板1】
bool is(ll x) {
for (int i = 2; i*i <= x; i++) {
if (x%i == 0)return false;
}
return true;//是质数
}
【直接能用的模板2】(会快一点)
=====代码=======
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 5;
int n;
ll ans;
bool isPrime[maxn];
int prime[maxn / 10], cnt;
void screen()//欧拉筛法求素数
{
cnt = 0;
memset(isPrime, 1, sizeof(isPrime));
//敢这么用大概是因为 是布尔表达式...
isPrime[0] = isPrime[1] = 0;
//先默认他们都是质数...
// 如果前面的到n能有达到的,那么它就不是质数。
//如果没达到那你就是质数.... 真经典啊....
for (int i = 2; i <= n; i++)
{
if (isPrime[i])
{
prime[cnt] = i;
cnt++;
ans += 2 * (n / i)*(cnt - 1);
//每找到一个素数i,其就可以与前面所有出现过的cnt-1个素数组成cnt-1个素数对,相应的就有2*(n/i)*(cnt-1)个数对
}
for (int j = 0; j<cnt; j++)
{
if (i*prime[j]>n) break;
isPrime[(i*prime[j])] = 0;
//if (i%prime[j] == 0) break;
}
}
}
int main()
{
scanf("%d", &n);
ans = 0;
screen();
cout << ans << endl;
}
另一个
//只要hash[0]为1 就不会败
//所以j从0开始检验 太重要了
//这份只用了97ms
#include<iostream>
using namespace std;
const int maxn = 1e7 + 5;
int prime[maxn];
bool vis[maxn];
int cnt;
void s(int n) {
cnt = 0;
memset(vis, true, sizeof(vis));
vis[0] = vis[1] = false;
for (int i = 2; i <= n; i++) {
if (vis[i]==1) {
prime[cnt++] = i;
}
for (int j = 0; i*prime[j] <= n; j++) {
vis[i*prime[j]] = false;
if (i%prime[j] == 0) {
break;
}
//那么,这三行是干什么的?竟然影响如此之大
}
}
return;
}
int main() {
int n;
scanf("%d", &n);
s(n);
long long ans = 0;
for (int i = 1; i < cnt; i++) {
ans += n / prime[i] * 2 * i;
}
printf("%lld\n", ans);
return 0;
}