Co-prime(容斥原理+筛一个数的素因子)

Co-prime

 HDU - 4135 

 

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.

InputThe 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).OutputFor 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}. 
题意:
  问一个区间[a,b]与n互素的数的个数。
题解:
  先找出n的素因子,比如n=30,那么找到30的素因子2 3 5,然后在区间[a,b]内用容斥原理找到2,3,5的倍数的个数ans,然后用区间长度减掉ans。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const ll maxn=1e6+10;
 8 ll n,cnt,ans;
 9 ll prime[maxn];
10 ll l,r;
11 ll gcd(ll a,ll b)
12 {
13     if(b==0)
14         return a;
15     else
16         return gcd(b,a%b);
17 }
18 ll Lcm(ll a,ll b)
19 {
20     return a*b/gcd(a,b);
21 }
22 ll get_prime(ll x)//如何找到x的素因子
23 {
24     for(ll i=2;i*i<=x;i++)
25     {
26         if(x%i)
27             continue;
28         while(x%i==0)
29             x/=i;
30         prime[cnt++]=i;
31     }
32     if(x!=1)            //如果x本身就是素数
33         prime[cnt++]=x;
34 }
35 int casen;
36 void dfs(ll m,ll th,ll now,ll step)
37 {
38 
39     ll lcm=Lcm(prime[th],now);
40     if(step&1)
41     {
42         ans+=m/lcm;
43     }
44     else
45     {
46         ans-=m/lcm;
47     }
48     for(ll i=th+1;i<cnt;i++)
49         dfs(m,i,lcm,step+1);
50 }
51 int main()
52 {
53     scanf("%d",&casen);
54     int ca=1;
55     while(casen--)
56     {
57         ans=0;
58         cnt=0;
59         scanf("%lld%lld%lld",&l,&r,&n);
60         get_prime(n);
61 
62         for(ll i=0;i<cnt;i++)
63             dfs(l-1,i,prime[i],1);
64         ll le=l-1-ans;
65         //cout<<le<<endl;
66         ans=0;
67         for(ll i=0;i<cnt;i++)
68             dfs(r,i,prime[i],1);
69         ll ri=r-ans;
70     //    cout<<ri<<endl; 
71         printf("Case #%d: %lld\n",ca++,ri-le);
72     }
73 }

 

posted @ 2018-10-31 19:26  *starry*  阅读(632)  评论(0编辑  收藏  举报