码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-02-09 19:27:32      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:ble   lld   位运算   分解质因子   cst   while   print   ++   素数   

<题目链接>

题目大意:

  给定区间[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不互质的数),再用区间的总数减去这些不互质数的个数即可。但是,由于在求不互质的数的时候,存在重复的计算,所以我们利用容斥对重复计算的数进行处理。容斥处理有多重表现形式,DFS、队列、位运算均可进行容斥处理。

得到一个数的所有质因子:

for(ll i=2;i*i<=m;i++) 
    if( m%i==0){   //得到m的所有的素因子
        vec.push_back(i);
        while(m%i==0)m/=i;
    }
if(m>1)vec.push_back(m);

 

 

位运算:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 vector<ll>vec;
 9 ll a,b,n;
10 
11 ll solve(ll x,ll m){     //[1,x]区间内与m4互质的数的个数
12     vec.clear();
13     for(ll i=2;i*i<=m;i++) if( m%i==0){   //得到m的所有的素因子
14         vec.push_back(i);
15         while(m%i==0)m/=i;
16     }
17     if(m>1)vec.push_back(m);
18     ll sum=0,val,cnt;
19     for(ll i=1;i<(1<<vec.size());i++){   //枚举所有素因子的乘积组合,用二进制表示哪几个因子被用到
20         val=1,cnt=0;
21         for(ll j=0;j<vec.size();j++){
22             if(i & (1<<j)) {
23                 val*=vec[j],cnt++;
24             }
25         }
26         //容斥,奇加偶减
27         if(cnt & 1)sum+=x/val;    // x/tval为[1,x]内为tval的倍数的数的个数
28         else sum-=x/val;
29     }
30     return x-sum;      //[1,x]的总数减去1~X中各素数倍数的总数
31 }
32 
33 int main(){
34     int T,ncase=0;scanf("%d",&T);while(T--){
35         scanf("%lld%lld%lld",&a,&b,&n);
36         ll ans=solve(b,n)-solve(a-1,n);
37         printf("Case #%d: %lld\n",++ncase,ans);
38     }
39 }

 

 

2019-02-09

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

标签:ble   lld   位运算   分解质因子   cst   while   print   ++   素数   

原文地址:https://www.cnblogs.com/00isok/p/10357829.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!