1. 程式人生 > >歐拉篩法(線性篩法)與解積性函數

歐拉篩法(線性篩法)與解積性函數

日常 rime ++ 下午 nbsp http image 發現 details

日常吐槽:嘖嘖嘖今天真是玄幻的一天。早上睡到9:10發現睡過了一個半小時,在9:30狂奔來機房 + 吃早餐,最後只剩一個半小時心態崩—>光榮爆零???又在下午四點把全部題改完???上午和下午的效率真的不是一個級別的啊...好的接下來把這道奇葩例題。

JZOJ 4732 函數

技術分享圖片技術分享圖片

題解

  23333這真的是出題人中的一股清流了,對建議打表的那三個點先表示感激(雖然我還是爆零因為壓根兒沒看懂題目)

  讓我們大膽地猜測一下,這個不知道是什麽鬼玩意兒的函數是什麽東西呢?好,拿起筆和草稿紙,模擬,沒錯!就!是!歐!拉!函!數!

  真是人生處處充滿驚喜啊,20分到手。

  還想再高一點,沒問題,直接加上個歐拉篩

,你已擁有50分。

  OKOK,你可以再用歐拉函數的積性函數特性,70分啦。

  打表的三個點最為玄學,參見下圖。

  技術分享圖片

    完美,接下來我們要做的就是AC了

代碼

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n, tot = 0;
int prime[(int)1e7 + 1], phi[(int)1e7 + 1];
int main()
{
    scanf("%d", &n);
    
if (n == (int)1e7 * 3) { printf("%lld\n", (long long)1e7 * 18); return 0; } if (n == 3) { printf("525162079891401242\n"); return 0; } if (n == 5) { printf("21517525747423580\n"); return 0; } phi[1] = 1;
for (int i = 2; i <= 1e7; i++) { if (!phi[i]) { prime[++tot] = i; phi[i] = i - 1; } for (int j = 1; j <= tot; j++) { if (i * prime[j] > 1e7) break; if (i % prime[j] != 0) phi[i * prime[j]] = phi[i] * phi[prime[j]]; else { phi[i * prime[j]] = phi[i] * prime[j]; break; } } } long long ans = 0; for (int i = 1; i <= n; i++) { int a; scanf("%d", &a); ans += phi[a]; } printf("%lld", ans); return 0; }

  23333全場最快不解釋,先嘚瑟一會兒(真的沒有故意卡!)

  順便貼兩個很好的博客文章,

  https://www.cnblogs.com/grubbyskyer/p/3852421.html

  https://blog.csdn.net/y20070316/article/details/51729812

歐拉篩法(線性篩法)與解積性函數