HDU-4135 Co-prime(容斥原理模板题)

26 篇文章 0 订阅

 

C - C

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Submit Status Practice HDU 4135

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

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,c求[a , b]范围中与c互质的数的个数。简化成 -> [1 , b] 中与c互质的数的个数 -  [1 , a) 中与c互质的数的个数

题目化简成了用两次 -> 容斥原理简单应用:求[1 , m]中与n互质的数的个数(btw,这里不是欧拉函数的应用!!)

套下模板就好了~~

这题我开的...傻兮兮的超时了首wa,被队友骂死。又是用到容斥原理啦要记住了呀!!!

【简单容斥原理模板】参考链接

typedef long long ll;
ll solve(ll x,ll n)//计算1~x中 与n互质的数的个数的模板
{
    vector<ll> vt;
    vt.clear();
    ll i,j;
    for(i=2;i*i<=n;i++)
        if(n%i==0)
        {
            vt.push_back(i);
            while(n%i==0)
                n/=i;
        }
    if(n>1)
        vt.push_back(n);
    
    ll sum=0,val,cnt;
    for(i=1;i<(1<<vt.size());i++)
    {
        val=1;
        cnt=0;
        for(j=0;j<vt.size();j++)
            if(i&(1<<j))
            {
                val*=vt[j];
                cnt++;
            }
        if(cnt&1)
            sum+=x/val;
        else
            sum-=x/val;
    }
    return x-sum;
}

【通过代码】 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#define go(i,a,b) for(ll i=a;i<=b;i++)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn = 1e6 + 5;
typedef long long ll;
ll solve(ll x,ll n)//计算1~x中 与n互质的数的个数的模板
{
    vector<ll> vt;
    vt.clear();
    ll i,j;
    for(i=2;i*i<=n;i++)
        if(n%i==0)
        {
            vt.push_back(i);
            while(n%i==0)
                n/=i;
        }
    if(n>1)
        vt.push_back(n);
    ll sum=0,val,cnt;
    for(i=1;i<(1<<vt.size());i++)
    {
        val=1;
        cnt=0;
        for(j=0;j<vt.size();j++)
            if(i&(1<<j))
            {
                val*=vt[j];
                cnt++;
            }
        if(cnt&1)
            sum+=x/val;
        else
            sum-=x/val;
    }
    return x-sum;
}
int main()
{
    ll t,a,b,c;
    scanf("%lld",&t);
    go(i,1,t)
    {
        scanf("%lld%lld%lld",&a,&b,&c);
        printf("Case #%lld: %lld\n",i,solve(b,c) - solve(a - 1,c));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值