hdu GCD(莫比乌斯反演+一点学习笔记)

GCD

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15999    Accepted Submission(s): 6152

 

Problem Description

Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.

Yoiu can assume that a = c = 1 in all test cases.

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.

Output

For each test case, print the number of choices. Use the format in the example.

Sample Input

2 1 3 1 5 1 1 11014 1 14409 9

Sample Output

Case 1: 9 Case 2: 736427

Hint

For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).

Source

2008 “Sunline Cup” National Invitational Contest

Recommend

wangye   |   We have carefully selected several similar problems for you:  1689 1690 1693 1691 1698 

题意:gcd(x,y)==k(1<=x<=b,1<=y<=d)的x,y的对数

题解:还是第一次涉及到莫比乌斯反演的题目,这里就先写一下对于莫比乌斯反演的一些理解吧,首先莫比乌斯反演是一种化简公式从而简化运算的一种方法,比如问题让我们求解F(n),那么我们可以先定义一个函数G(n),使得G(n)=sigma(F(d)){d|n} ,因为G(n)我们已知,那么就可以通过莫比乌斯反演公式F(n)=sigma(u(d/n)*G(d)){d|n}求出F(n)了。(u是一个容斥因子)

对于这道题求sigma([gcd(x,y)==k])(1<=x<=b,1<=y<=d) 可以转换成sigma(gcd(x/k,y/k)==1)-->sigma(gcd(x,y)==1){1<=x<=b/k,1<=y<=d/k} 则F(n)=sigma([gcd(i,j)==n]){i<=b/k,j<=d/k},那么可以构造函数G(n)=sigma(n|gcd(i,j)){1<=i<=b/k,1<=j<=d/k}  因为G(n)=sigma(F(d)){n|d}(注意这里和前面不一样了),则莫比乌斯反演函数可以写成F(n)=sigma(u(d/n)*G(d)){n|d} 则F(1)即为所求答案,但因为还有重复的地方,减去即可。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define SI(i) scanf("%lld",&i)
#define PI(i) printf("%lld\n",i)
using namespace std;
typedef long long ll;
const int mod=998244353;
const int MAX=1e6+7;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
int dir[9][2]={0,1,0,-1,1,0,-1,0, -1,-1,-1,1,1,-1,1,1};
template<class T>bool gmax(T &a,T b){return a<b?a=b,1:0;}
template<class T>bool gmin(T &a,T b){return a>b?a=b,1:0;}
template<class T>void gmod(T &a,T b){a=((a+b)%mod+mod)%mod;}
typedef pair<ll,ll> PII;

int mu[MAX],vis[MAX],prime[MAX];
void get_mobi()
{
    mu[1]=1;
    int tot=0;
    for(int i=2;i<MAX;i++)
    {
        if(!vis[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=tot&&i*prime[j]<MAX;j++)
        {
            if(i*prime[j]>MAX) break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                 mu[i*prime[j]]=0;
                 break;
            }
            else mu[i*prime[j]]=-mu[i];
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    get_mobi();
    for(int cas=1;cas<=T;cas++)
    {
        int a,b,c,d,k;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);

        printf("Case %d: ",cas);

        if(!k)
        {
            printf("0\n");
            continue;
        }

        int N=min(b,d);
        b/=k;d/=k;
        if(b>d) swap(b,d);

        ll ans=0,tmp=0;
        for(int i=1;i<=N;i++)
        {
            ans+=1LL*mu[i]*(b/i)*(d/i);
            tmp+=1LL*mu[i]*(b/i)*(b/i);
        }

        printf("%lld\n",ans-tmp/2);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sudu6666/article/details/82427160
今日推荐