hdu5608 function

口胡

  来看这个傻逼式子,令 g(x)=x23x+2
  那就是 g(x)=d|xf(d)
  傻逼莫比乌斯反演
   f(x)=d|xμ(d)g(xd)
  你不是求 f 的前缀和吗,直接硬套杜教筛的式子肯定不行,因为 g 并不是积性函数(随便举个例子 g(2)=0 g(3)=2 g(6)=20 )。
  那就开始乱搞
  

i=1ng(i)=i=1nd|if(d)=i=1nd=1nif(d)

  令 s(x)=xi=1f(i)
  
i=1ng(i)=i=1ns(ni)s(n)=i=1ng(i)i=2ns(ni)

  然后就 O(n23logn) 预处理加 O(Tn23) 回答。
  怎么感觉好暴力啊预处理那块

代码

//莫比乌斯反演、杜教筛 
#include <cstdio>
#include <algorithm>
#define maxn 1000005
#define mod 1000000007ll
#define ll long long
using namespace std;
ll big[maxn+10], small[maxn+10], N, inv, prime[maxn/10], mu[maxn], f[maxn], g[maxn];
bool mark[maxn];
inline ll s1(ll x){return x*(1+x)/2%mod;}
inline ll s2(ll x){return x*(x+1)%mod*(2*x+1)%mod*inv%mod;}
inline ll gs(ll x){return (s2(x)-3*s1(x)+2*x)%mod;}
inline ll gets(ll n){return n<maxn?small[n]:big[N/n];}
void calc(ll n)
{
    if(n<maxn or gets(n))return;
    ll i, last, &s=big[N/n];
    s=gs(n);
    for(i=2;i<=n;i=last+1)
    {
        last=n/(n/i);
        if(!gets(n/i))calc(n/i);
        s=(s-(last-i+1)*gets(n/i))%mod;
    }
}
void init()
{
    ll i, j;
    mu[1]=1;
    for(i=2;i<maxn;i++)
    {
        if(!mark[i])prime[++*prime]=i, mu[i]=-1;
        for(j=1;i*prime[j]<maxn;j++)
        {
            mark[i*prime[j]]=1;
            if(i%prime[j]==0)break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(i=1;i<maxn;i++)g[i]=(i*i-3*i+2)%mod;
    for(i=1;i<maxn;i++)for(j=i;j<maxn;j+=i)f[j]=(f[j]+mu[i]*g[j/i])%mod;
    for(i=1;i<maxn;i++)small[i]=(small[i-1]+f[i])%mod;
}
int main()
{
    inv=166666668;
    init();
    ll T;
    scanf("%lld",&T);
    while(T--)
    {
        for(int i=1;i<=1005;i++)big[i]=0;
        scanf("%lld",&N);
        calc(N);
        printf("%lld\n",(gets(N)+mod)%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fsahfgsadhsakndas/article/details/71759793