hdu 4135 Co-prime 容斥定理

题目:
A - Co-prime
Time Limit: 1000 MS Memory Limit: 32768 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

[Submit] [Status]

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

题意:
a到b之间有几个与n互质的数;
思路:
暴力肯定超时,所以用容斥定理;
a到b之间有几个互质的数,可以理解为求1~b之间与n互质的数的个数-1~a-1之间与n的互质的数的个数,求与n互质可以理解为求总个数减去不互质的个数,不互质怎么求呢,可以把n分解质因数,那么b里是n的质因数的倍数的一定不与n互质,所以可以把b里每个n的质因数的倍数都求出来,然后减去重复的,结果为:b/2+b/3+b/5-b/(2*3)-b/(2*5)-b/(3*5)+b/(2*3*5),容斥定理,奇加偶减;

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1e7;
long long int a[maxn];
long long int  num=0;
void init(long long int n)
{
    num=0;
    for(int j=2; j<=sqrt(n); j++)
    {
        if(n%j==0)
        {
            a[num++]=j;
            while(n%j==0)
                n=n/j;
        }
    }


    if(n>1)
    {
        a[num++]=n;
    }
}
long long rongchi(long long m)
{
    long long int que[10000],i,j,k,sum=0;
    long long int t=0;
    que[t++]=-1;

    for(i=0; i<num; i++)
    {
        k=t;
        for(j=0; j<k; j++)
        {
            que[t++]=que[j]*a[i]*(-1);
        }
    }


    for(i=1; i<t; i++)
        sum=sum+m/que[i];
    return sum;
}
int main()
{
    int T;
    scanf("%d",&T);
    int p=0;
    while(T--)
    {


        p++;
        long long int a,b,n;
        scanf("%lld%lld%lld",&a,&b,&n);
        init(n);
        long long int ans=(b-rongchi(b))-(a-1-rongchi(a-1));
        printf("Case #%d: %lld\n",p,ans);


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值