【模板】杜教篩(Sum)
阿新 • • 發佈:2019-01-09
傳送門
Description
給定一個正整數\(N(N\le2^{31}-1)\)
求
\[ans1=\sum_{i=1}^n \varphi(i)\]
\[ans_2=\sum_{i=1}^n \mu(i)\]
Solution
總算是寫了一個不會\(TLE\)的杜教篩,不想用\(map\),因此上了一個很醜的\(Hash\)……
Code
#include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define MN 1900000 int cnt,pr[MN]; bool mark[MN]; struct Node{int id;ll phi,mu;}MI[MN]; inline void init() { register int i,j; for(i=1;i<MN;++i) MI[i].id=i; MI[1].phi=MI[1].mu=1; for(i=2;i<MN;++i) { if(!mark[i]){pr[++cnt]=i;MI[i].phi=i-1;MI[i].mu=-1;} for(j=1;j<=cnt&&i*pr[j]<MN;++j) { #define now i*pr[j] mark[now]=true; if(i%pr[j]==0){MI[now].mu=0;MI[now].phi=MI[i].phi*pr[j];break;} else MI[now].mu=-MI[i].mu,MI[now].phi=MI[i].phi*(pr[j]-1); #undef now } } for(i=1;i<MN;++i) MI[i].phi+=MI[i-1].phi,MI[i].mu+=MI[i-1].mu; } class Hash { #define mod 23333 private: std::vector<Node> a[mod]; int ha,i; Node em; public: Hash(){em=(Node){0,0ll,0ll};}; inline void insert(int id,ll phi,ll mu){a[id%mod].push_back((Node){id,phi,mu});} inline Node find(int id) { ha=id%mod; for(i=a[ha].size()-1;~i;--i) if(a[ha][i].id==id) return a[ha][i]; return em; } }HA; inline Node calc(int n) { if(n<MN) return MI[n]; register Node ans,tmp; if((ans=HA.find(n)).id) return ans; ll ret1=1ll,ret2=1ll*n*(n+1)/2ll; for(register ll i=2,j;i<=n;i=j+1) j=n/(n/i),tmp=calc(n/i),ret1-=(j-i+1)*tmp.mu,ret2-=(j-i+1)*tmp.phi; ans=(Node){n,ret2,ret1};HA.insert(n,ret2,ret1); return ans; } int main() { init(); register int T,n; T=read(); register Node ans; while(T--) { n=read(); ans=calc(n); printf("%lld %lld\n",ans.phi,ans.mu); } return 0; }
Blog來自PaperCloud,未經允許,請勿轉載,TKS!