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

HDU 1695 GCD (莫比乌斯反演)

时间:2016-08-16 11:51:53      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

传送门


GCD

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


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).

题目大意:

[1,b][1,d] 区间中 GCD(x,y)==k 的对数,GCD(3,2)GCD(2,3) 被认为是一样的。

解题思路:

这个题目,我当时是用容斥原理 + 欧拉函数写的,过了 现在学到莫比乌斯反演又打算用这个写,因为这算是一个入门的题目,

那么我们就想办法来构造那两个函数 f(n)F(n) ,那么我们现在来设 f(k)表示的是GCD(x,y)==k 的对数,其中

(1<=x<=b,1<=y<=d) 为了保证最后的唯一性,那么我们默认为 b<=d,那么我们再来构造 F(n) ,设 F(k)

GCD(x,y)==k 那么显然有 F(k)=floor(bk)?floor(dk) 那么根据莫比乌斯反演有:

f(i)=i|kmu(ki)?F(k)=i|dmu(ki)?floor(bk)?floor(dk)

然后进行去重就行了。

My Code

/**
2016 - 08 - 16 上午
Author: ITAK

Motto:

今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 1e6+5;
const int MOD = 1e9+7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL Scan_LL()///输入外挂
{
    LL res=0,ch,flag=0;
    if((ch=getchar())==‘-‘)
        flag=1;
    else if(ch>=‘0‘&&ch<=‘9‘)
        res=ch-‘0‘;
    while((ch=getchar())>=‘0‘&&ch<=‘9‘)
        res=res*10+ch-‘0‘;
    return flag?-res:res;
}
int Scan_Int()///输入外挂
{
    int res=0,ch,flag=0;
    if((ch=getchar())==‘-‘)
        flag=1;
    else if(ch>=‘0‘&&ch<=‘9‘)
        res=ch-‘0‘;
    while((ch=getchar())>=‘0‘&&ch<=‘9‘)
        res=res*10+ch-‘0‘;
    return flag?-res:res;
}
void Out(LL a)///输出外挂
{
    if(a>9)
        Out(a/10);
    putchar(a%10+‘0‘);
}
int mu[MAXN], p[MAXN], k;
bool prime[MAXN];
void Mobius()
{
    memset(prime, 0, sizeof(prime));
    mu[1] = 1;
    k = 0;
    for(int i=2; i<MAXN; i++)
    {
        if(!prime[i])
        {
            p[k++] = i;
            mu[i] = -1;
        }
        for(int j=0; j<k&&i*p[j]<MAXN; j++)
        {
            prime[i*p[j]] = 1;
            if(i%p[j] == 0)
            {
                mu[i*p[j]] = 0;
                break;
            }
            mu[i*p[j]] = -mu[i];
        }
    }
}

int main()
{
    Mobius();
    int T;
    T = Scan_Int();
    for(int cas=1; cas<=T; cas++)
    {
        LL a, b, c, d, k;
        a = Scan_LL();
        b = Scan_LL();
        c = Scan_LL();
        d = Scan_LL();
        k = Scan_LL();
        if(k==0LL || k>b || k>d)
        {
            printf("Case %d: 0\n",cas);
            continue;
        }
        d /= k;
        b /= k;
        if(b > d)
            swap(b, d);
        LL ret = 0, ans = 0;
        for(LL i=1; i<=b; i++)
            ret += mu[i]*(b/i)*(d/i);
        for(LL i=1; i<=b; i++)
            ans += mu[i]*(b/i)*(b/i);
        ret -= (ans>>1LL);
        printf("Case %d: %I64d\n",cas,ret);
    }
    return 0;
}

HDU 1695 GCD (莫比乌斯反演)

标签:

原文地址:http://blog.csdn.net/qingshui23/article/details/52218121

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