【hdu 4135】Co-prime

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

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

Source
The Third Lebanese Collegiate Programming Contest

【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=4135

【题解】

要求【a..b】这个区间范围内和N互质的数的个数;
可以这样
先求出1..a-1这个范围内和N互质的数的个数A
求出1..b这个范围内和N互质的数的个数B
B-A就是答案了;
求1..X范围内和N互质的数这个问题;
可以转换一下
先求出1..X里面不和N互质的数的个数;
这点
需要先把N质因数分解(几个质数的成绩)一下;
把它的所有质因子处理出来(不用记录具体每个质因子有多少个);
假如N = 6,X = 20
5=2*3
则2的倍数与6都不互质,则ans+=20/2
3的倍数与6都不互质,则ans+=20/3
但是有2和3的公共倍数被重复计算了
则还要减去
即ans-=20/(2*3);
更一般的
我们会发现,出现奇数个数,就用加法,偶数个数用减法。
换一种说法
假设N有num个质因子
则对应二进制有num个数字,每个数字为0或1
把那些为1的位的质因子全部乘上来->temp;
如果1的个数为奇数则ans+X/temp;
否则减去X/temp;
这样就能算出1..X里面不和N互质的数的个数了;

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int MAXN = 10000;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);

LL a,b,n,pri[MAXN];
int num;

LL get_ans(LL x)
{
    LL ans = 0;
    rep1(i,1,(1<<num)-1)
    {
        LL y = 1,f = 0;
        rep1(j,1,num)
            if (i & (1<<(j-1)))
            {
                y = y*pri[j];
                f++;
            }
        if (f&1)
            ans += x/y;
        else
            ans -= x/y;
    }
    ans = x-ans;
    return ans;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    int T;
    rei(T);
    rep1(ii,1,T)
    {
        num = 0;
        rel(a);rel(b);rel(n);
        for (LL i = 2;i*i<=n;i++)
            if ((n%i)==0)
            {
                pri[++num] = i;
                while ((n%i)==0)
                    n/=i;
            }
        if (n > 1)
            pri[++num] = n;
        printf("Case #%d: %I64d\n",ii,get_ans(b)-get_ans(a-1));
    }
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(120)  评论(0)    收藏  举报