Co-prime HDU

来源:互联网 发布:李银桥和权延赤 知乎 编辑:程序博客网 时间:2024/06/05 11:05


HDU _4135 Co_prime 


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.

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 <= 10 9).

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.

Input

2
1 10 2
3 15 5

Output

Case #1: 5
Case #2: 10


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>  求在区间a,b里与 n  互质的数有多少个。

思路: 大概算一个模板吧: 首先考虑 欧拉函数,明显不行,数据太大。那么就考虑先算出1~a 中与 n 互质的数,再算1~b 中与 n 互质的数,然后ans=  solve(b)-solve(a);
问题就变为了 1~a  中与 n  互质的数怎么求,博客上COPY  的思路:
对于 1~ a  ,我们先考虑  与  n 不互质的数,然后互质的数就是  a-Solve(a);
对于不互质的数: 先分解 n 找到 素因子,不互质的数就是 a 以内素因子的倍数的个数。
举个例子:
 n= 20   素因子 ={  2,5 }
 a=15    那么  不互质的个数就是  15/2+15/5 ={2,4,6,8,10,12,14}+{5,10,15}=10-1=9;

那么对于 素因子存在 上例中  {10} 这个数在两个集合中都出现,此时就需要用到 容斥原理。
然后就是容斥 的实现了。
容斥的实现 有些技巧,便于理解我给出一个 每步的进行,
以 1 12  30  为例子。




代码:


#pragma comment(linker, "/STACK:1024000000,1024000000")//#include <bits/stdc++.h>#include<string>#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<queue>#include<stack>#include<vector>#include<algorithm>#define maxn 1001000#define INF 0x3f3f3f3f#define eps 1e-8#define MOD 1000000007#define ll long longusing namespace std;ll Q[maxn],fac[maxn];ll num;void Divide(ll n){    num=0;    for(ll i=2;i*i<=n;i++)    {        if(n%i==0)        {            while(n%i==0)                n/=i;            fac[num++]=i;        }    }    if(n!=1) fac[num++]=n;}ll solve(ll n){    ll k,t,ans;    t=ans=0;    Q[t++]=-1;    for(ll i=0;i<num;i++)    {       // cout<<"num "<<num<<endl;        k=t;        for(ll j=0;j<k;j++)        {            Q[t++]=-1*Q[j]*fac[i];           // printf("fac[%lld]->%lld  -- Q[%lld] -> %lld\n",i,fac[i],t-1,Q[t-1]);        }    }    for(ll i=1;i<t;i++)    {        ans+=n/Q[i];    }    return ans;}int main(){    int T,kase=1;    scanf("%d",&T);    while(T--)    {        ll a,b,n;        scanf("%lld%lld%lld",&a,&b,&n);        Divide(n);        ll ans=b-solve(b)-(a-1-solve(a-1));        printf("Case #%d: %lld\n",kase++,ans);    }    return 0;}


原创粉丝点击