Loading [MathJax]/extensions/TeX/mathchoice.js

[hdu5608]function

题意:d|nf(d)=n23n+2,求\sum_{i=1}^{n}f(i)\mod 10^{9}+7 , n \leqslant 10^{9} \left( T \leqslant 500\right)组数据,只有5组>10^{6}

题解:看了式子感觉像是反演,但是呢....

S(n)=\sum_{i=1}^{n}f(i)

那么S(n)=\sum_{i=1}^{n}\sum_{d|i}f(d)=\sum_{i=1}^{n}f(d)\lfloor\frac{n}{d}\rfloor=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor} f(d)=\sum_{d=1}^{n}S(\lfloor\frac{n}{d}\rfloor)=\sum_{i=1}^{n}(i-1)*(i-2)

所以S(n)=\frac{n*(n-1)*(n-2)}{3}-\sum_{i=2}^{n}f(i)

所以老套路,预处理maxn^{\frac{2}{3}}的S(i),这个可以直接算,总复杂度也是O(n^{\frac{2}{3}})

复制代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#define MAXN 5000000
#define mod 1000000007
#define inv 333333336
#define ll long long
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int f[MAXN+5];
map<int,ll> mp;

ll calc(int x)
{
    if(x<=MAXN)return f[x];
    map<int,ll>::iterator it;
    if((it=mp.find(x))!=mp.end())return it->second;
    ll sum=1LL*x*(x-1)%mod*(x-2)%mod*inv%mod;
    int last;
    for(int i=2;i<=x;i=last+1)
    {
        last=x/(x/i);
        sum-=1LL*(last-i+1)*calc(x/i);
        while(sum<0)sum+=mod;
    }
    return (mp[x]=sum);
}

int main()
{
    for(int i=1;i<=MAXN;i++)
        f[i]=1LL*(i-2)*(i-1)%mod;
    for(int i=1;i<=MAXN;i++)
        for(int j=i<<1;j<=MAXN;j+=i)
            f[j]=(f[j]-f[i]+mod)%mod;
   // for(int i=1;i<=10;i++)cout<<f[i]<<endl;
    for(int i=2;i<=MAXN;i++) f[i]=(f[i]+f[i-1])%mod;
    for(int t=read();t;t--)
        printf("%lld\n",calc(read()));
    return 0;
}
复制代码

 

posted @   FallDream  阅读(430)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示