码迷,mamicode.com
首页 > 其他好文 > 详细

1190 最小公倍数之和 V2【莫比乌斯反演】

时间:2018-01-20 12:38:06      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:isp   str   details   void   space   ==   source   end   include   

参考:http://blog.csdn.net/u014610830/article/details/49493279
这道题做起来感觉非常奇怪啊……头一次见把mu推出来再推没了的……
\[ \sum_{i=a}^{b}lcm(i,b) \]
\[ \sum_{i=a}^{b}\frac{i*b}{gcd(i,b)} \]
\[ \sum_{d|b}\sum_{i=a}^{b}[gcd(i,b)==d]\frac{ib}{d} \]
\[ \sum_{d|b}\sum_{i=\left \lfloor \frac{a}{d} \right \rfloor}^{\left \lfloor \frac{b}{d} \right \rfloor}[gcd(i,b)==1]\frac{idb}{d} \]
\[ b\sum_{d|b}\sum_{i=\left \lfloor \frac{a}{d} \right \rfloor}^{\left \lfloor \frac{b}{d} \right \rfloor}[gcd(i,b)==1]i \]
\[ b\sum_{d|b}\sum_{i=\left \lfloor \frac{a}{d} \right \rfloor}^{\left \lfloor \frac{b}{d} \right \rfloor}i\sum_{k|gcd(i,\frac{b}{d})}\mu(k) \]
\[ b\sum_{d|b}\sum_{k|\frac{b}{d}}\mu(k)\sum_{i=\left \lfloor \frac{a}{d} \right \rfloor}^{\left \lfloor \frac{b}{d} \right \rfloor,k|i}i \]
\[ b\sum_{d|b}\sum_{k|\frac{b}{d}}\mu(k)k\sum_{i=\left \lfloor \frac{a}{dk} \right \rfloor}^{\left \lfloor \frac{b}{dk} \right \rfloor}i \]

\[ f(a,b)=\sum_{i=a}^{b}i \]
\[ b\sum_{d|b}\sum_{k|\frac{b}{d}}\mu(k)kf(\left \lfloor \frac{a}{dk} \right \rfloor,\left \lfloor \frac{b}{dk} \right \rfloor) \]
枚举dk
\[ b\sum_{d|b}f(\frac{a}{d},\frac{b}{d})\sum_{k|d}\mu(k)k \]
其中f可以\( O(1) \)算,设\( g(x)=\sum_{k|x}\mu(k)k \),容易发现这是积性的,显然设p为质数,\( g(p)=1-p,g(p^k)=1-p \),于是这样就把mu推掉了
时间复杂度很不科学但是还是能过

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=100005,m=100000,inv2=500000004,mod=1e9+7;
int T,n,q[N],tot,a,b,p[N],cnt,len[N];
bool v[N];
vector<int>fac;
void dfs(int re,int l)
{
    if(l>cnt)
    {
        fac.push_back(re);
        return;
    }
    int tmp=1;
    dfs(re,l+1);
    for(int i=1;i<=len[l];i++)
    {
        tmp*=p[l];
        dfs(re*tmp,l+1);
    }
}
int main()
{
    v[1]=1;
    for(int i=2;i<=m;i++)
    {
        if(!v[i])
            q[++tot]=i;
        for(int j=1;j<=tot&&i*q[j]<=m;j++)
        {
            int k=i*q[j];
            v[k]=1;
            if(i%q[j]==0)
                break;
        }
    }
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&b);
        cnt=0;
        int now=b;
        for(int i=1;i<=tot&&q[i]*q[i]<=now;i++)
        {
            if(now%q[i]==0)
            {
                p[++cnt]=q[i];
                len[cnt]=0;
            }
            while(now%q[i]==0)
            {
                now/=q[i];
                len[cnt]++;
            }
        }
        if(now>1)
        {
            p[++cnt]=now;
            len[cnt]=1;
        }
        fac.clear();
        dfs(1,1);//cout<<cnt<<endl;
        long long ans=0ll;
        for(int i=0;i<fac.size();i++)
        {
            int v=fac[i];
            long long tt=a+v-1,tmp,re=1ll;
            tmp=(((tt/v+b/v)%mod)*((b/v-tt/v+1+mod)%mod)%mod)*inv2%mod;
            for(int j=1;j<=cnt;j++)
                if(v%p[j]==0)
                    re=re*((1-p[j]+mod)%mod)%mod;
            ans=((ans+re*tmp%mod)%mod+mod)%mod;
        }
        printf("%lld\n",ans*b%mod);
    }
    return 0;
}

1190 最小公倍数之和 V2【莫比乌斯反演】

标签:isp   str   details   void   space   ==   source   end   include   

原文地址:https://www.cnblogs.com/lokiii/p/8320189.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!