HDU 4135 Co-prime(容斥原理 + 基础数论)

传送门

Co-prime

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3695    Accepted Submission(s): 1461


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

Source
题目大意: 给一个区间 [a,b] 求这个区间中 与 n 互素的个数。 解题思路: 这个问题可以转化为求 [1,b] 区间中与 n 互素的个数 ans1 减去 [1,a1] 区间中与 n 互素的个 数 ans2 ,那么 [1,x] 区间中与 n 互素的个数怎么求呢,可以先将 n 进行素因子分解,然后用区间 x 除以 素因子,就得到了与 n 的 约数是那个素因子的个数,然后每次这样求一遍,但是发现有重 复的:举个例子 [1,10] 区间中与 6 互素的个数,应该是 10(10/2+10/3) 但是这样多减去 了他们的最小公倍数 6 的情况,所以在加上 10/6 也就是:

10(10/2+10/310/6)=3

这就用到了容斥原理,知道了这个,题目也就可以做了,先进行素因子分解,然后二进制枚举子集

进行容斥原理(奇加偶减):

My Code

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

Motto:

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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
bool prime[MAXN];
LL p[MAXN];
int k;
///素数筛选
void isprime()
{
    k = 0;
    memset(prime, 0, sizeof(prime));
    for(LL i=2; iif(!prime[i])
        {
            p[k++] = i;
            for(LL j=i*i; j1;
        }
    }
}
LL fac[MAXN/100];
int cnt = 0;
void Dec(LL x)
{
    cnt = 0;
    for(int i=0; p[i]*p[i]<=x&&iif(x%p[i]==0)
        {
            fac[cnt++] = p[i];
            while(x%p[i]==0)
                x /= p[i];
        }
    }
    if(x > 1)
        fac[cnt++] = x;
}
LL Solve(LL x)
{
    LL ret = 0;
    for(LL i=1; i<(1LL<int sum = 0, tmp = 1;
        for(int j=0; jif(i & (1LL<if(sum & 1)
            ret += x/tmp;
        else
            ret -= x/tmp;
    }
    return ret;
}
int main()
{
    isprime();
    int T;
    LL N, A, B;
    scanf("%d",&T);
    for(int cas=1; cas<=T; cas++)
    {
        scanf("%I64d%I64d%I64d",&A,&B,&N);
        Dec(N);
        printf("Case #%d: %I64d\n",cas,B-Solve(B)-A+1+Solve(A-1));
    }
    return 0;
}

你可能感兴趣的:(ACM_容斥原理,ACM_HDU,ITAK的ACM之路)