hdu1695 GCD

来源:互联网 发布:钓鱼软件什么意思 编辑:程序博客网 时间:2024/06/18 16:17

转载请注明出处,谢谢http://blog.csdn.net/bigtiao097?viewmode=contents

题意

给定整数a,b,c,d,k,a=c=1求axc,  byd(1c,d,k105)且gcd(x,y)=k的数对(x,y)有多少对.

思路

这个题比bzoj2818 稍微复杂一点,可以看一下这里
由于a,b不相等,不能像bzoj2818一样用欧拉函数来做了
莫比乌斯反演轻松解决

g(n)=n|df(d)f(n)=n|dμ(dn)g(d)

f(n)代表   gcd(x,y)=n   xy
g(n)gcd(x,y)%n=0  xy
这样就有了
g(n)=n|df(d)

然后利用反演公式,因为g(n)非常的好求,g(n)=cn×dn
根据上述的反演公式直接计算就可以了
还有一点就是这个题要求(x,y)和(y,x)视为相同的,所以需要去重,怎么去呢,其实很简单
我们在算完axc,  byd,再算一下axmin(c,d),  bymin(c,d),然后减一下就行


具体代码如下:
Result:Accepted    Memory: 2268KB    Time : 31MS

#include<bits/stdc++.h>typedef long long ll;using namespace std;const int maxn=1e5+5;bool vis[maxn];int prime[maxn];int mu[maxn];int n,a,b,c,d,k;int tot;ll ans1,ans2;int Case;void mobius(){    memset(vis,0,sizeof vis);    mu[1] = 1;    tot = 0;    for(int i = 2; i <maxn; i++)    {        if( !vis[i] ){            prime[tot++] = i;            mu[i] = -1;        }        for(int j = 0; j < tot; j++)        {            if(i * prime[j] >=maxn) break;            vis[i * prime[j]] = true;            if( i % prime[j] == 0)            {                mu[i * prime[j]] = 0;                break;            }            else                mu[i * prime[j]] = -mu[i];        }    }}int main(){    ios::sync_with_stdio(false);    mobius();    int T;    cin>>T;    while(T--)    {        ans1 = 0;        ans2 = 0;        cin>>a>>b>>c>>d>>k;        cout<<"Case "<<++Case<<": ";        if(k==0)        {            cout<<0<<endl;            continue;        }        n = min(b,d);        for(int x=k;x<=n;x+=k)        {            ans1+= 1LL*mu[x/k]*(b/x)*(d/x);            ans2+= 1LL*mu[x/k]*(n/x)*(n/x);        }        ans2--;        cout<<ans1-ans2/2<<endl;    }}
原创粉丝点击