hdu 5608 function

来源:互联网 发布:淘宝微淘粉丝怎么增加 编辑:程序博客网 时间:2024/05/22 02:13

===s(n)i=1nf(n)i=1n(i23i+2)i=1nd|i,d<if(d)n(n+1)(2n+1)63n(n+1)2+2ni=2nd=1nif(d)

杜教筛即可。预处理的时候做不到线性了,但是仍然可以O(klogk)做到。

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxn=800000,maxm=3000000,p=1000000007,mod=1000007,inv2=500000004,inv6=166666668;int f[maxn+10],sum[maxn+10],fir[mod+10],ne[maxm],val[maxm],ans[maxm],tot;int inc(int x,int y){    x+=y;    return x>=p?x-p:x;}int dec(int x,int y){    x-=y;    return x<0?x+p:x;}int get(int n){    return inc(dec((LL)n*(n+1)%p*(2*n+1)%p*inv6%p,3LL*n%p*(n+1)%p*inv2%p),2*n%p);}int find(int n){    for (int i=fir[n%mod];i;i=ne[i])        if (val[i]==n) return ans[i];    return -1;}void ins(int n,int x){    int y=n%mod;    tot++;    ne[tot]=fir[y];    fir[y]=tot;    val[tot]=n;    ans[tot]=x;}int calc(int n){    if (n<=maxn) return sum[n];    int ret=find(n);    if (ret>=0) return ret;    ret=get(n);    for (int i=2,j;i<=n;i=j+1)    {        j=n/(n/i);        ret=dec(ret,(LL)(j-i+1)*calc(n/i)%p);    }    ins(n,ret);    return ret;}int main(){    for (int i=1;i<=maxn;i++)    {        f[i]=inc(f[i],inc(dec((LL)i*i%p,3*i%p),2));        sum[i]=inc(sum[i-1],f[i]);        for (int j=i+i;j<=maxn;j+=i)            f[j]=dec(f[j],f[i]);    }    int T,n;    scanf("%d",&T);    while (T--)    {        scanf("%d",&n);        printf("%d\n",calc(n));    }}
原创粉丝点击