Co-prime(HDU-4135)

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

题意:给出一个整数区间 [a,b],与一个整数 n,求区间中与 n 互素的数的个数

思路:

问题可转换为区间 [1,b] 中与 n 互素的数的个数减去区间 [1,a-1]中与 n 互素的数的个数

那么问题就是转化为对于 n,求 1~k 中与 n 互质的数有多少个,因此可以先反着来求 1~k 中与 n 不互质的数有多少个

故可对 n 进行因子分解,然后从 1~k 中减去不能与 n 整除的数的个数,然后根据容斥定理,奇加偶减,那么最后答案就是:1~b 的元素个数减去 1~a-1 的元素个数再减去 1~b 中与 n 不互质的数的个数加上 1~a-1 中与 n 互质的数的个数

即:b-(a-1)-calculate(b)+calculate(a-1)

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 2000000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;

bool bprime[N];
LL prime[N],factor[N];
LL cnt;
void isprime() {//筛素数
    cnt=0;
    memset(bprime,false,sizeof(bprime));

    for(LL i=2; i<N; i++) {
        if(!bprime[i]) {
            prime[cnt++]=i;
            for(LL j=i*i; j<N; j+=i)
                bprime[i]=true;
        }
    }
}
LL calculate(LL m,LL num) {
    LL res=0;
    for(LL i=1; i<(1<<num); i++) {
        LL sum=0;
        LL temp=1;
        for(LL j=0; j<num; j++) {
            if(i&(1<<j)) {
                sum++;
                temp*=factor[j];
            }
        }
        if(sum%2)
            res+=m/temp;
        else
            res-=m/temp;
    }
    return res;
}

int main() {
    isprime();

    LL t;
    scanf("%d",&t);
    int Case=1;
    while(t--) {
        LL a,b,n;
        scanf("%lld%lld%lld",&a,&b,&n);

        LL num=0;
        for(LL i=0; prime[i]*prime[i]<=n&&i<cnt; i++) {
            if(n%prime[i]==0) {//记录n的因子
                factor[num++]=prime[i];
                while(n%prime[i]==0)
                    n/=prime[i];
            }
        }

        if(n!=1)//1既不是素数也不是合数
            factor[num++]=n;

        //容斥定理,奇加偶减,
        LL res=(b-(a-1)-calculate(b,num))+calculate(a-1,num);

        printf("Case #%d: %lld\n",Case++,res);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值