hdu4135题解 容斥

Problem Description
Given a number N, you are asked to count the number of integers between A and B inclusive which are relatively prime to N.
Two integers are said to be co-prime or relatively prime if they have no common positive divisors other than 1 or, equivalently, if their greatest common divisor is 1. The number 1 is relatively prime to every integer.
 

Input
The first line on input contains T (0 < T <= 100) the number of test cases, each of the next T lines contains three integers A, B, N where (1 <= A <= B <= 10 15) and (1 <=N <= 10 9).
 

Output
For each test case, print the number of integers between A and B inclusive which are relatively prime to N. Follow the output format below.
 

Sample Input
  
2 1 10 2 3 15 5
 

Sample Output
  
Case #1: 5 Case #2: 10
Hint
In the first test case, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.
首先感谢ACM不懈的追求大神的博客,本题解的代码是在该大神的题解的基础上完成的:http://www.cnblogs.com/jiangjing/archive/2013/06/03/3115470.html
题目大意:给定整数N,求出多少a到b区间(包含a,b,以下关于区间的描述都包括边界),有多少个数字和N互质。
思路:因为数量巨大,如果用辗转相除法会造成超时。我们应该回归互质的定义:两个数字的最大公约数为1称之为互质。故两数互质和两数不互质(印象里面好像叫做互余吧)互为独立事件(这说话的腔调真是受不了。。。)。总而言之,如果我们能求出该区间有多少个数字和N不互质就好了。
那么怎么求不互质的个数呢?(设问既有过渡的功能也有引起读者兴趣的作用,哈哈,好了不扯了),好的,我们先把问题改成求1到b区间和N不互质的个数,我们要先找出N的所有质因数,并求出这些质因数相乘可以组合成哪些数字,并求出b除以这些数字的和(不保留小数部分),并且因为有重叠的部分,我们这时候就需要用到互斥定理,例如:b=10,N=48,那么质因数为2,3。这些质因数相乘的组合有:1,2,3,6(可以选择只要其中一个数甚至不选),这时候用互斥定理,答案就是:int(10/-1)+int(10/2)+int(10/3)+int(10/-6),同理,我们可以求出1到a-1区间和N不互质的个数。
最难的骨头啃下来了,我们可以求出答案,假设1到b区间和N不互质的个数为f(b),假设1到a-1区间和N不互质的个数为f(a-1),那么题目的答案就是b-f(b)-(a-1-f(a-1)),好的,此处应该有掌声.
//hud 4135
#include<cstdio>
#include<iostream>
#include<vector>
#define maxn 100005
using namespace std;
vector <__int64> factor;
__int64 p[maxn];
int len_p;
void getfactor(__int64 x)
{
    factor.clear();
    for(__int64 i = 2; i * i <= x; i ++)
    {
        if(x % i == 0)
        {
            factor.push_back(i);
            while(x % i == 0)
            {
                x /= i;
            }
        }
    }
    if(x > 1)
    {
        factor.push_back(x);
    }
}
void getp()
{
    p[0] = -1;
    len_p = 1;
    int len_factor = factor.size();
    for(__int64 i = 0; i < len_factor; i ++)
    {
        int k = len_p;
        for(__int64 j = 0; j < k; j ++)
        {
            p[len_p ++] = factor[i] * p[j] * (-1);
        }
    }
}
__int64 f(__int64 x)
{
    __int64 ans = 0;
    for(int i = 1; i < len_p; i ++)
    {
        ans += (x / p[i]);
    }
    return ans;
}
int main()
{
    int d,cas = 1;
    cin >> d;
    while(d --)
    {
        __int64 a, b, n;
        scanf("%I64d%I64d%I64d", &a, &b, &n);
        getfactor(n);
        printf("Case #%d: ", cas ++);
        getp();
        cout << b - f(b) - (a - 1 - f(a - 1)) << endl;
    }
    return 0;
}
/*
2
1 10 2
3 15 5
ans:5 10
*/

posted @ 2015-01-01 13:59  MrYu4  阅读(22)  评论(0编辑  收藏  举报