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 }
View Code

 

posted @ 2018-01-19 19:31  Blue233333  阅读(221)  评论(0编辑  收藏  举报