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 <= 1015) and (1 <=N <= 109).
 

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
*/

發佈了44 篇原創文章 · 獲贊 12 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章