HDU 4135 Co-prime(容斥原理 + 基础数论)

传送门

Co-prime

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3695    Accepted Submission(s): 1461

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

Source

题目大意:

给一个区间 [a,b] 求这个区间中 与 n 互素的个数。

解题思路:

这个问题可以转化为求 [1,b] 区间中与 n 互素的个数 ans1 减去 [1,a?1] 区间中与 n 互素的个

数 ans2 ,那么 [1,x] 区间中与 n 互素的个数怎么求呢,可以先将 n 进行素因子分解,然后用区间

x 除以 素因子,就得到了与 n 的 约数是那个素因子的个数,然后每次这样求一遍,但是发现有重

复的:举个例子 [1,10] 区间中与 6 互素的个数,应该是 10?(10/2+10/3) 但是这样多减去

了他们的最小公倍数 6 的情况,所以在加上 10/6 也就是:

10?(10/2+10/3?10/6)=3

这就用到了容斥原理,知道了这个,题目也就可以做了,先进行素因子分解,然后二进制枚举子集

进行容斥原理(奇加偶减):

My Code:

/**
2016 - 08 - 08 上午
Author: ITAK

Motto:

今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 1e6+5;
const int MOD = 1e9+7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
bool prime[MAXN];
LL p[MAXN];
int k;
///素数筛选
void isprime()
{
    k = 0;
    memset(prime, 0, sizeof(prime));
    for(LL i=2; i<MAXN; i++)
    {
        if(!prime[i])
        {
            p[k++] = i;
            for(LL j=i*i; j<MAXN; j+=i)
                prime[j] = 1;
        }
    }
}
LL fac[MAXN/100];
int cnt = 0;
void Dec(LL x)
{
    cnt = 0;
    for(int i=0; p[i]*p[i]<=x&&i<k; i++)
    {
        if(x%p[i]==0)
        {
            fac[cnt++] = p[i];
            while(x%p[i]==0)
                x /= p[i];
        }
    }
    if(x > 1)
        fac[cnt++] = x;
}
LL Solve(LL x)
{
    LL ret = 0;
    for(LL i=1; i<(1LL<<cnt); i++)
    {
        int sum = 0, tmp = 1;
        for(int j=0; j<cnt; j++)
        {
            if(i & (1LL<<j))
            {
                sum++;
                tmp *= fac[j];
            }
        }
        if(sum & 1)
            ret += x/tmp;
        else
            ret -= x/tmp;
    }
    return ret;
}
int main()
{
    isprime();
    int T;
    LL N, A, B;
    scanf("%d",&T);
    for(int cas=1; cas<=T; cas++)
    {
        scanf("%I64d%I64d%I64d",&A,&B,&N);
        Dec(N);
        printf("Case #%d: %I64d\n",cas,B-Solve(B)-A+1+Solve(A-1));
    }
    return 0;
}
时间: 2024-08-24 23:59:33

HDU 4135 Co-prime(容斥原理 + 基础数论)的相关文章

hdu 4135 Co-prime【容斥原理】

Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1668    Accepted Submission(s): 636 Problem Description Given a number N, you are asked to count the number of integers between A and B

HDU 4135 Co-prime(容斥+数论)

Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5526    Accepted Submission(s): 2209 Problem Description Given a number N, you are asked to count the number of integers between A and B

[容斥原理] hdu 4135 Co-prime

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4135 Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1176    Accepted Submission(s): 427 Problem Description Given a number N, you are a

HDU 4002 Find the maximum(数论-欧拉函数)

Find the maximum Problem Description Euler's Totient function, φ (n) [sometimes called the phi function], is used to determine the number of numbers less than n which are relatively prime to n . For example, as 1, 2, 4, 5, 7, and 8, are all less than

hdu 1301 Jungle Roads (基础最小生成树)

题目: 链接:点击打开链接 题意: 对n个村庄之间的路进行修理, 然后是n-1行,每行的第一组数据时一个大写字母VIL和一个数K,Vil表示从这个村庄出发,K表示刚才的那个字母代表的村庄和其他村庄的路的数目,接下来在同一行是K组数据,每组是一个大写字母和一个数,大写字母表示和第一个村庄连接的村庄,数表示维修他们之间的路所需的费用.现在为了使维修费油最低,只需所维修的路使每个村庄都是直接或间接的连接即可,求最小的费用. 思路: 只需把输入数据处理好即可.其他都是kruskal模板.' 代码: #i

HDU - 1098 - Ignatius&#39;s puzzle (数论 - 费马小定理)

Ignatius's puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7012    Accepted Submission(s): 4847 Problem Description Ignatius is poor at math,he falls across a puzzle problem,so he has no

HDU 1754 I Hate It 基础线段树

用区间值m表示这段区间的最大值,一直更新这个区间的最大值,很基础的线段树 #include<iostream> #include<stdio.h> using namespace std; #define N 200005 struct node{ int l,r,m; }tree[N*4]; int a[N]; void build(int left,int right,int i){ tree[i].l=left; tree[i].r=right; if(tree[i].l==

HDU 4944 FSF’s game(数论+递推)

#include <cstdio> #include <cstring> typedef unsigned long long ll; const ll MOD = (1ULL<<32); const int N = 500001; int t, n; ll ans[N], frc[N]; void init() { for (ll i = 1; i < N; i++) { for (ll j = i; j < N; j += i) { ll tmp = j

hdu how many prime numbers 筛选法求素数

/* * hdu How many prime numbers * date 2014/5/13 * state AC */ #include <iostream> #include <cmath> #include <cstdio> using namespace std; bool isPrime(int x) { int sqr=sqrt(x*1.0); for(int i=2;i<=sqr;i++) { if(x%i==0)return false; }