hdu5608:function
$n^2-3n+2=\sum_{d|i}f(i)$,问$f(i)$前$n$项和。
方法一:直接切入!
$S(n)=\sum_{i=1}^{n}f(i)=\sum_{i=1}^{n}(i^2-3i+2-\sum_{d|i,d<i}f(d))=\sum_{i=1}^{n}(i^2-3i+2)-\sum_{i=1}^{n}\sum_{d|i,d<i}f(d)=\frac{n(n+1)(2n+1)}{6}-\frac{3n(n+1)}{2}+2n-\sum_{k=2}^{n}\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}f(d)$
且不管他是不是什么积性函数了,符合杜教筛形式直接算!!
方法二:仔细乱搞
这一看就是反演形式,那就令$g(n)=n^2-3n+2$,反演得
$f(n)=\sum_{d|n}\mu (d)g(\frac{n}{d})=\sum_{d|n}\mu(d)(\frac{n}{d})^2-3\sum_{d|n}\mu(d)\frac{n}{d}+2\sum_{d|n}\mu(d)=h(n)-3\varphi (n)+2[n=1]$
现在需要知道这三坨东西的前缀和。其中欧拉函数之前写过了,[n=1]的话。。然后就剩个$h(n)$也就是$\sum_{d|n}\mu(d)(\frac{n}{d})^2$。
$\sum_{i=1}^{n}\sum_{d|i}\mu (d)(\frac{i}{d})^2=\sum_{k=1}^{n}k^2\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu (d)$。
莫比乌斯的前缀和就可以杜教筛啦!!
方法一是便捷的方式,但方法二是常用的套路,各有千秋。代码方法一。
1 #include<string.h> 2 #include<stdlib.h> 3 #include<stdio.h> 4 #include<math.h> 5 //#include<assert.h> 6 #include<algorithm> 7 //#include<iostream> 8 //#include<bitset> 9 using namespace std; 10 11 int T,n,pr; 12 #define maxn 1000011 13 #define LL long long 14 const int mod=1e9+7; 15 LL s[maxn],f[maxn]; 16 void pre(int n) 17 { 18 for (int i=1;i<=n;i++) 19 { 20 f[i]+=1ll*i*i-3*i+2; 21 for (int j=i+i;j<=n;j+=i) f[j]-=f[i]; 22 } 23 for (int i=1;i<=n;i++) s[i]=((s[i-1]+f[i])%mod+mod)%mod; 24 } 25 26 struct Edge{int to,v,next;}; 27 #define maxh 1000007 28 struct Hash 29 { 30 int first[maxh],le; Edge edge[maxn]; 31 Hash() {le=2;} 32 void insert(int y,int v) 33 {int x=y%maxh; Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 34 int find(int y) 35 {int x=y%maxh; for (int i=first[x];i;i=edge[i].next) if (edge[i].to==y) return edge[i].v; return -1;} 36 }h; 37 38 int six=(mod+1)/6,two=(mod+1)>>1; 39 int calc(int n) 40 { 41 if (n<=pr) return s[n]; 42 int tmp=h.find(n); if (tmp!=-1) return tmp; 43 int tot=0; 44 for (int i=2,last;i<=n;i=last+1) 45 { 46 last=n/(n/i); 47 tot+=(last-i+1)*1ll*calc(n/i)%mod; 48 tot-=tot>=mod?mod:0; 49 } 50 int ans=((six*1ll*n%mod*(n+1)%mod*(2*n+1)%mod-two*3ll*n%mod*(n+1)%mod+2*n)%mod+mod)%mod; 51 ans=(ans-tot+mod)%mod; 52 h.insert(n,ans); 53 return ans; 54 } 55 56 int main() 57 { 58 pre(pr=1000000); 59 scanf("%d",&T); 60 while (T--) scanf("%d",&n),printf("%d\n",calc(n)); 61 return 0; 62 }