hdu5608 function

来源:互联网 发布:手机压缩文件解压软件 编辑:程序博客网 时间:2024/06/01 10:36

口胡

  来看这个傻逼式子,令g(x)=x23x+2
  那就是g(x)=d|xf(d)
  傻逼莫比乌斯反演
  f(x)=d|xμ(d)g(xd)
  你不是求f的前缀和吗,直接硬套杜教筛的式子肯定不行,因为g并不是积性函数(随便举个例子g(2)=0g(3)=2g(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 longusing 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;}
0 0
原创粉丝点击