luogu 3768 简单的数学题 (莫比乌斯反演+杜教筛)
题目大意:略 洛谷传送门
杜教筛入门题?
以下都是常规套路的变形,不再过多解释
$\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ijgcd(i,j)$
$\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ij\sum\limits_{d|gcd(i,j)}\varphi(d)$
$\sum\limits_{d=1}^{N} \varphi(d) \sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ij$
$\sum\limits_{d=1}^{N} \varphi(d) d^{2} \sum\limits_{i=1}^{\left \lfloor \frac{N}{d} \right \rfloor}\sum\limits_{j=1}^{\left \lfloor \frac{N}{d} \right \rfloor}ij$
令$f(d)=\varphi(d) d^{2}$,由于$\varphi(d)$和$1(d)$都是积性函数,所以$f(d)$是积性函数
数据范围好像有点大?$n \leq 10^{10}$?杜教筛!
考虑设计一个和$f$搭配且同为积性函数$g$,且$(f*g)$能很快计算出来,令$f(n)$前缀和是$S(n)$
给出杜教筛的推导式
$S(n)=\sum\limits_{i=1}^{N}(f*g)(i)-\sum\limits_{i=2}^{N}g(i)S(\left \lfloor \frac{N}{i} \right \rfloor)$
根据常见狄利克雷卷积形式$id=1*\varphi$,容易推出比较优秀的$g(d)=d^{2}$,那么$(f*g)(n)=\sum\limits_{d|n}f(d)*g(\frac{n}{d})=\varphi(d) d^{2}(\frac{n}{d})^{2}=n^{3}$
$g$的前缀和就是平方和,$(f*g)$的前缀和就是立方和,可以$O(1)$求出来
一定要多取模,不然有些地方可能会爆$longlong$
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N1 5000010 5 #define M1 3000010 6 #define ll long long 7 #define dd double 8 #define cll const long long 9 using namespace std; 10 11 const int maxn=5000000; 12 13 void exgcd(ll a,ll b,ll &x,ll &y) 14 { 15 if(!b){ x=1; y=0; return; } 16 exgcd(b,a%b,x,y); ll t=x; x=y; y=t-a/b*y; 17 } 18 struct Hsh{ 19 #define M 3000000 20 int head[M1],nxt[M1],val[M1],cte;ll to[M1]; 21 void ins(ll x,int w) 22 { 23 int j,y=x%M;ll v; 24 for(j=head[y];j;j=nxt[j]){ v=to[j]; if(v==x) return; } 25 cte++; to[cte]=x; val[cte]=w; nxt[cte]=head[y]; head[y]=cte; 26 } 27 int query(ll x) 28 { 29 int j,y=x%M;ll v; 30 for(j=head[y];j;j=nxt[j]){ v=to[j]; if(v==x) return val[j]; } 31 return -1; 32 } 33 #undef M 34 }h; 35 36 ll n,m,inv2,inv6; 37 int use[N1],pr[N1],cnt,phi[N1]; 38 ll f[N1],sf[N1]; 39 void get_mu(cll &jr) 40 { 41 int i,j; phi[1]=f[1]=sf[1]=use[1]=1; 42 for(i=2;i<=maxn;i++) 43 { 44 if(!use[i]){ pr[++cnt]=i; phi[i]=i-1; } 45 for(j=1;j<=cnt&&i*pr[j]<=maxn;j++) 46 { 47 use[i*pr[j]]=1; 48 if(i%pr[j]){ phi[i*pr[j]]=phi[i]*(pr[j]-1)%jr; } 49 else{ phi[i*pr[j]]=phi[i]*pr[j]%jr; break; } 50 } 51 f[i]=1ll*i*i%jr*phi[i]%jr; 52 sf[i]=(sf[i-1]+f[i])%jr; 53 } 54 } 55 int F(ll x,cll &jr) 56 { 57 if(x<=maxn) return sf[x]; 58 ll ans=h.query(x); if(ans!=-1) return ans; 59 ll i,la,pi,pla; ans=x%jr*(x+1)%jr*inv2%jr; ans=ans*ans%jr; 60 for(i=2;i<=x;i=la+1){ 61 la=x/(x/i); pi=i%jr; pla=la%jr; 62 ans-=(1ll*pla%jr*(pla+1)%jr*(2*pla+1)%jr-1ll*(pi-1)%jr*(pi)%jr*(2*pi-1)%jr)*inv6%jr*F(x/i,jr)%jr; 63 } 64 ans=(ans%jr+jr)%jr; 65 h.ins(x,ans); 66 return ans; 67 } 68 69 int main() 70 { 71 scanf("%lld%lld",&m,&n); 72 cll jr=m; get_mu(jr); ll i,la,x,y,ans=0; 73 exgcd(6,jr,inv6,y); exgcd(2,jr,inv2,y); inv6=(inv6%jr+jr)%jr; inv2=(inv2%jr+jr)%jr; 74 for(i=1;i<=n;i=la+1) 75 { 76 la=n/(n/i); 77 if((n/i)&1) x=(n/i+1)/2%jr*((n/i)%jr)%jr; 78 else x=(n/i)/2%jr*((n/i+1)%jr)%jr; 79 ans=(x*x%jr*(F(la,jr)-F(i-1,jr)+jr)+ans)%jr; 80 } 81 printf("%lld\n",ans); 82 return 0; 83 }