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.
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 三个数 你要找出[a,b]范围内与n互质(即最大公约数为1)的个数 ,我们可以分别求[1,a-1]和[1,b]中互质个数然后我们要求就是 [1,b]  -  [1,a-1]

互质个数怎么求 ,互质个数相当于 总数减去不互质个数  ,显然n的质因子的所有倍数都是不互质的

比如  b=12,n=30   

n的质因子为 2 ,3 5

[1,12]中 2的倍数有 2 ,4 ,6 , 8,10, 12 =n/2=6个

[1,12]中3的倍数有 3, 6 ,9, 12=n/3=4个

[1,12]中5的倍数有 5 ,10 =n/5=2个

不过显然其中有重复的我们应该去掉

用容斥定理 公式=n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(3*4*5)

怎么实现可以看代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stack>
#include<vector>
#include<queue>
#include<map>
#define nn 500
#define mm 100001
#define inff 0x3fffffff
#define ll long long
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
int n;
ll a,b,m,num;
ll q[mm],fa[110];//fa存n所有的质因子,q存所有质因子的组合
void aa(ll p)
{
    num=0;
    for(ll i=2;i*i<=p;i++)
    {
        if(p%i==0)
        {
            while(p%i==0) p/=i;
            fa[num++]=i;
        }
    }
    if(p>1) fa[num++]=p;
}
ll bb(ll u)//容斥定理
{
    ll k,t,ans;
    t=ans=0;
    q[t++]=-1;
    for(ll i=0;i<num;i++)
    {
        k=t;
        for(ll j=0;j<k;j++)//每一个新的质因子都会和前面所有的组合进行一次组合
            q[t++]=-1*q[j]*fa[i];
    }
    for(ll i=1;i<t;i++)
        ans+=u/q[i];
    return ans;
}
int main()
{
  scanf("%d",&n);
  for(int yyy=1;yyy<=n;yyy++)
  {
      scanf("%lld%lld%lld",&a,&b,&m);
      aa(m);
      ll ans=b-bb(b)-(a-1-bb(a-1));
      printf("Case #%d: ",yyy);
      printf("%lld\n",ans);
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值