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

关于数论【莫比乌斯反演】

时间:2017-09-22 14:04:30      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:printf   cst   false   .com   blank   ems   style   维护   一个   

由于这个证明过程太过长。。。推荐大家看这个大佬的博文,我就是看这个学会的 http://www.cnblogs.com/chenyang920/p/4811995.html

然后推荐一个求u数组更为有效的方式,利用线性筛选素数:

(例题是hdu1695)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
bool v[1100000];
int prime[1100000],u[1100000];
void Mobius_inversion()//利用线性筛选素数来维护u 
{
    memset(v,false,sizeof(v));
    int pr=0;u[1]=1;
    for(int i=2;i<=1000000;i++)
    {
        if(v[i]==false)
        {
            prime[++pr]=i;
            u[i]=-1;//本身是个质数,1个质数乘积
        }
        for(int j=1;j<=pr,i*prime[j]<=1000000;j++)
        {
            v[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                u[i*prime[j]]=0;//除开质数的两种情况 
                break;
            }
            else u[i*prime[j]]=-u[i];//多了一个数的乘积,与前一个相反 
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    Mobius_inversion();
    for(int tt=1;tt<=T;tt++)
    {
        int a,b,c,d,k;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k==0){printf("Case %d: 0\n",tt);continue;}
        b/=k;a/=k;
        d/=k;c/=k;
        if(b>d)swap(b,d);
        
        LL ans1=0;
        for(int i=1;i<=b;i++)
            ans1+=(LL)u[i]*(b/i)*(d/i);//带入 G(n) 的公式 有  F(1) = sigma(u[i]*(a/i)*(b/i)) (1<=i<=N)
        LL ans2=0;
        for(int i=1;i<=b;i++)
            ans2+=(LL)u[i]*(b/i)*(b/i);
        ans1-=ans2/2;
        printf("Case %d: %lld\n",tt,ans1);
    }
    return 0;
}

 

关于数论【莫比乌斯反演】

标签:printf   cst   false   .com   blank   ems   style   维护   一个   

原文地址:http://www.cnblogs.com/AKCqhzdy/p/7574398.html

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