容斥 - HDU 4135 Co-prime

Co-prime

Problem‘s Link: http://acm.hdu.edu.cn/showproblem.php?pid=4135



推荐: 容斥原理

Mean:

给你一个区间[l,r]和一个数n,求[l,r]中有多少个数与n互素。

analyse:

经典的容斥原理题。

如果题目是说求1~n中有多少个数与n互质,我们一定反应应该是欧拉函数。

但是如果n特别大或者说是求某个给定区间与n互素的个数,这时用欧拉函数就行不通。

容斥做法:首先我们可以在O(sqrt(n))内求出n的所有质因数p1,p2,p3....pk。

对于每个质因数pi,1~r中不与它互素的个数就是r/pi。

然后就是如何容斥了?

首先我们来分析,n<=1e9,那么n的质因数的个数最多不超过9个,那么我们就可以对n的所有质因数进行组合来计算。

例如:30的质因数有3个(2,3,5),我们可以用二进制来表示所有的情况:

001: 5

010: 3

011: 3 5

100: 2

101: 2 5

110: 2 3

111: 2 3 5

假设有k个质因数,那么只需用2^k-1个数的二进制来表示即可。

剩下的就是容斥了,设cnt为1的个数(选中的质因数的个数),当cnt为奇数,sum加上此次的;cnt为偶数,sum减去此次的。

具体看代码。

Time complexity: O(N)

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-10-19.49
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;

LL solve(LL r,LL n)
{
     vector<LL> ve;
     LL up=(LL)sqrt(n);
     for(LL i=2;i<=up;++i)
     {
           if(n%i==0)
           {
                 ve.push_back(i);
                 while(n%i==0)
                       n/=i;
           }
     }
     if(n>1) ve.push_back(n);
     LL sum=0,si=ve.size();
     up=(1<<si)-1;
     for(LL i=1;i<=up;++i)
     {
           LL tmp=i,bits=0,mul=1,cnt=0;
           while(tmp)
           {
                 if(tmp&1)
                 {
                       mul*=ve[bits];
                       ++cnt;
                 }
                 ++bits;
                 tmp=tmp>>1;
           }
           LL cur=r/mul;
           if(cnt&1) sum+=cur;
           else sum-=cur;
     }
     return sum;
}

int main()
{
     ios_base::sync_with_stdio(false);
     cin.tie(0);
     LL t,cas=1;
     cin>>t;
     while(t--)
     {
           LL l,r,n;
           cin>>l>>r>>n;
           if(l>r) swap(l,r);
           printf("Case #%lld: %lld\n",cas++,r-l+1-(solve(r,n)-solve(l-1,n)));
     }
     return 0;
}
/*

*/

时间: 2024-08-06 14:20:11

容斥 - HDU 4135 Co-prime的相关文章

数论 + 容斥 - HDU 4059 The Boss on Mars

The Boss on Mars Problem's Link Mean: 给定一个整数n,求1~n中所有与n互质的数的四次方的和.(1<=n<=1e8) analyse: 看似简单,倘若自己手动推公式的话,还是需要一定的数学基础. 总的思路:先求出sum1=(1^4)+(2^4)+...(n^4),再求出sum2=(1~n中与n不互质的数的四次方的和),answer=sum1-sum2. 如何求sum1呢? 有两种方法: 1.数列差分.由于A={Sn}={a1^4+a2^4+...an^4}

HDU 4135 Co-prime (分解质因数 + 容斥)

Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2314    Accepted Submission(s): 865 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(组合+容斥)

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 tha

HDU 4135 Co-prime 区间内与n互质的个数 容斥(入门

题目链接:点击打开链接 题意:给定区间[l, r] 询问区间内有多少个数和n互质 思路: solve(x) 表示[1,x]区间内与n互质的个数,则ans = solve(r)-solve(l-1); 与n互质的个数=所有数-与n不互质的数=所有数-(与n有一个因子-与n有2个因子的+与n有3个因子的) 状压n的因子个数,然后根据上面的公式容斥得到. #include <stdio.h> #include <iostream> #include <algorithm> #

题解报告:hdu 4135 Co-prime(容斥定理入门)

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

hdu 4135 Co-prime(素数分解 容斥)

容斥做,欧拉好像比这个麻烦??? 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 6 using namespace std; 7 typedef long long ll; 8 9 ll solve(ll a,ll n){ 10 vector<ll> v; 11 for(ll i = 2 ; i*i <= n ; i ++){

HDU 4135 Co-prime(容斥:二进制解法)题解

题意:给出[a,b]区间内与n互质的个数 思路:如果n比较小,我们可以用欧拉函数解决,但是n有1e9.要求区间内互质,我们可以先求前缀内互质个数,即[1,b]内与n互质,求互质,可以转化为求不互质,也就是有除1的公因数.那么我们把n质因数分解,就能算出含某些公因数的不互质的个数.因为会重复,所以容斥解决.因为因数个数可能很多(随便算了一个20!> 2e18,所以质因数分解个数不会超过20个),我们可以用二进制来遍历解决. #include<set> #include<map>

HDU 4135 Co-prime (容斥+分解质因子)

<题目链接> 题目大意: 给定区间[A,B](1 <= A <= B <= 10 15)和N(1 <=N <= 10 9),求出该区间中与N互质的数的个数. 解题分析: 将求区间[A,B]与N互质的数转化成求[1,B] 区间与N互质的个数  -  [1,A-1]中与N互质的个数.同时,因为直接求区间内与N互质的数不好求,我们从反面入手,求出与N不互质的数,借鉴埃筛的思想,我们先求出N的所有质因子,然后将这些质因子在区间内倍数的个数全部求出(即与N不互质的数),再用