アイデア:ドゥは、ふるいを教えます
提出:\(2 \)回
間違った理由:\(\ varphi(I)\)プレフィックスとと\(整数\)保存
ソリューション:
乗法関数でふるいにかけたプレフィックスとの問題については、線形問題よりも低くてもよいふるい時間の複雑さを教えるデュ。
最初の設定しなければなりません\(F * G = H \) 、および\(H \)プレフィックスが簡単、見つける\(G \)間隔やすさの要件を。
具体的には:
\ [\ sum_ {I = 1} ^ {N-} H(I)= \ sum_ {I = 1} ^ {N-} \ sum_ {D | I} CDOT F(\ G(D)\ FRAC { I}、{D})\] \ [\ sum_ {I = 1} ^ {N-} H(I)= \ sum_ {D = 1} ^ {N-} G(D)\ sum_ {I = 1} ^ { {N} \ lfloorの\のFRAC {
D} \ rfloor} F({I})\] 設け\(S(n)が\)を表し\(\ sum_ {i = 1 } ^ {n}はF(i)を\)
\ [\ sum_ {i = 1 } ^ {n}はH(I)= \ sum_ {D = 1} ^ {n}はG(D)\ CDOT S(\ lfloorの\のFRAC {n}が{D} \ rfloor) \]
(1)\ [G \ CDOT S(N)= \ sum_ {I = 1} ^ {N-} H(I) - \ sum_ {D = 2} ^ {N-} G(D)\ CDOT S( \ lfloorの\のFRAC {n}が{
D} \ rfloor)\] を探している我々バックブロックに分割式、場合\(S(n)を\)複雑である(O(N ^ {\ \ FRACを{2} {3}})\)
それが構築する方法主に\(H \)と\(G \)を
さて直接言う:
\(\イプシロン= MU \ \ CDOT I \)
(上記ID \ varphi \ CDOT I \言及=)\
する\(F(N)= \ varphi(N)\ CDOT N ^ K = \ varphiを(N ^ {K + 1} )\) メソッドのクラスである:
\(^ ID + 1 {K} = F \ CDOT ID ^ K \)。
#include<cstdio>
#include<iostream>
#include<unordered_map>
#include<cmath>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=5000000,Inf=2147483647;
int T,n,cnt,p[N/4],mu[N+10];
ll phi[N+10];
bool v[N+10];
inline void PRE() { phi[1]=mu[1]=1;
for(R i=2;i<=N;++i) {
if(!v[i]) p[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(R j=1;j<=cnt&&i*p[j]<=N;++j) {
v[i*p[j]]=true;
if(i%p[j]==0) {
mu[i*p[j]]=0;
phi[i*p[j]]=phi[i]*p[j]; break;
} mu[i*p[j]]=-mu[i];
phi[i*p[j]]=phi[i]*(p[j]-1);
}
}
for(R i=1;i<=N;++i) mu[i]+=mu[i-1];
for(R i=1;i<=N;++i) phi[i]+=phi[i-1];
}
unordered_map<int,int> memmu;
unordered_map<int,ll> memphi;
inline ll s_phi(int n) {
if(n<=N) return phi[n];
if(memphi.count(n)) return memphi[n];
register ll ans=0;
for(R l=2,r;r<Inf&&l<=n;l=r+1) {
r=n/(n/l),ans+=(r-l+1)*s_phi(n/l);
} return memphi[n]=1llu*n*(n+1ll)/2ll-ans;
}
inline int s_mu(int n) {
if(n<=N) return mu[n];
if(memmu.count(n)) return memmu[n];
register ll ans=0;
for(R l=2,r;r<Inf&&l<=n;l=r+1) {
r=n/(n/l),ans+=(r-l+1)*s_mu(n/l);
} return memmu[n]=1ll-ans;
}
inline void main() {
PRE(); g(T); while(T--) {
g(n); printf("%lld %d\n",s_phi(n),s_mu(n));
}
}
} signed main() {Luitaryi::main(); return 0;}
2019年8月23日
77