《Liberoj6235. 区间素数个数》
求区间的素数个数。
可以构造一个积性函数f(i) = 1.
然后Min25筛统计质数和即可。
这里习惯性把F(x)写成了prime[i],其实应该是1.
对Min25的理解又加深了很多~
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 1e6+5; const int M = 1e6+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; LL sum1[N],prime[N],id1[N],id2[N],g1[N],w[N]; LL n,Sqr,tot = 0,m = 0; bool flag[N]; LL f1(LL x){return x - 1;} LL F(LL x){return 1;} int getid(LL x) { if(x <= Sqr) return id1[x]; else return id2[n/x]; } void init() { Sqr = sqrt(n),tot = 0,m = 0; for(int i = 2;i <= Sqr;++i) { if(!flag[i]) { prime[++tot] = i; sum1[tot] = sum1[tot-1]+1; } for(int j = 1;j <= tot && prime[j]*i <= Sqr;++j) { flag[i*prime[j]] = 1; if(i%prime[j] == 0) break; } } for(LL L = 1,r;L <= n;L = r+1) { r = (n/(n/L)),w[++m] = (n/L); g1[m] = f1(w[m]); if(w[m] <= Sqr) id1[w[m]] = m; else id2[n/w[m]] = m; } for(int i = 1;i <= tot;++i){ for(int j = 1;j <= m && prime[i]*prime[i] <= w[j];++j){ g1[j] = g1[j] - F(prime[i]) * (g1[getid(w[j] / prime[i])] - sum1[i-1]); } } } int main() { n = read(); init(); printf("%lld\n",g1[getid(n)]); system("pause"); return 0; }