hdu1695gcd(Mobius反演)

莫比乌斯反演的资料
http://wenku.baidu.com/view/542961fdba0d4a7302763ad5.html

http://baike.baidu.com/link?url=1qQ-hkgOwDJAH4xyRcEQVoOTmHbiRCyZZ-hEJxRBQO8G0OurXNr6Rh6pYj9fhySI0MY2RKpcaSPV9X75mQv0hK

莫比乌斯反演的两种形式,书上一般只介绍第一种。
公式
这道题用的是第二种。
f(k)是1<=x<=b,1<=y<=d中gcd(x,y)==k的个数
F(k)是1<=x<=b,1<=y<=d中gcd(x,y)是k的倍数的个数
F(k)=(b/k)*(d/k)。
并且这道题转化为
f(k) =f(1)是1<=x<=b/k,1<=y<=d/k中gcd(x,y)==1的个数
也就是求f
(1)=sigma(i<=min(b,d)) u(i)F(i)

还有另一种推法
Sigma(d|n) u(d)=(n==1)。
这道题就是相当于求
Sigma(1< =i< =x) Sigma(1< =j< =y) (gcd(i,j)==1)=
Sigma(1< =i< =x) Sigma(1< =j< =y)Sigma(d|gcd(i,j))u(d)=
Sigma(1< =i< =x) Sigma(1< =j< =y) Sigma(d|i且d|j)u(d)=
Sigma(d)u(d)*Sigma(1< =i< =x且d|i) Sigma(1< =j< =y且d|j)=
Sigma(d)u(d)* (x/i) *(y/i).

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ms(X) memset(X,0,sizeof(X))
#define mcs(X) memset(X,-1,sizeof(X))
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int mobius[100020];
void getMbs(void)
{
    ms(mobius);
    for(int i=1;i<=100000;i++)
    {
        int target=(i==1?1:0);
        int delta=target-mobius[i];
        mobius[i]=delta;
        for(int j=(i<<1);j<=100000;j+=i)
            mobius[j]+=delta;
    }
}
int main()
{
    int t,ti=0;
    cin>>t;
    getMbs();
    while(++ti<=t)
    {
        int a,b,c,d,k;
        scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
        if(!k) {printf("Case %d: 0\n",ti);continue;}
        b/=k,d/=k;
        if(b>d){int tmp=b;b=d;d=tmp;}
        LL res1=0,res2=0;
        for(int i=1;i<=b;i++)
            res1+=(LL)mobius[i]*(b/i)*(d/i);
        for(int i=1;i<=b;i++)
            res2+=(LL)mobius[i]*(b/i)*(b/i);
        printf("Case %d: %I64d\n",ti,res1-res2/2);
    }
    return 0;
}

你可能感兴趣的:(acm之路,数论初步,组合数学)