Co-prime HDU - 4135

本文介绍了一种解决HDU_4135Co_prime问题的方法,该问题要求计算在指定区间内与给定整数互质的所有整数的数量。通过分解给定整数的素因子,并利用容斥原理来计算结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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 <= 10 15) 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 long
using 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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值