zoukankan      html  css  js  c++  java
  • 容斥原理的二进制实现模版

    最近学习容斥原理,实现容斥原理大致有三种方法:dfs,队列数组,二进制。

    今天主要讲下二进制实现容斥原理:

       有一个集合{A1……An},求集合的子集?很显然答案为

    也就是2^n个,也就是每一个子集有唯一标志符 i (0<i<2^n,空集除外),也就是说有唯一的二进制表示!

    代码看下面的:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<iomanip>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<vector>
     8 #include<stdlib.h>
     9 using namespace std;
    10 int prime[40000],m;
    11 bool f[40000];
    12 vector<int>p;//存放质因数
    13 //用筛法初始化40000以内的质数,将质数存放在prime数组中,m记录大小
    14 int init(){
    15     m=0;
    16     for(int i=2; i<40000; i++){
    17         if (f[i]==0) prime[m++]=i;//质数
    18         //筛去合数
    19         for (int j=0; j<m&&i*prime[j]<40000; j++){
    20             f[i*prime[j]]=1;
    21             if (i%prime[j]==0) break;//保证每个数只筛去一次
    22         }
    23     }
    24 }
    25 //对n分解质因数
    26 void factor(int n){
    27     p.clear();
    28     for (int i=0; i<m&&prime[i]*prime[i]<=n; i++){
    29         if (n%prime[i]==0){
    30             p.push_back(prime[i]);
    31             n/=prime[i];
    32             while (n%prime[i]==0)
    33                 n/=prime[i];
    34         }
    35     }
    36     if(n>1) p.push_back(n);
    37 }
    38 //用二进制实现容斥原理,求区间[1,r]内与n互素的数的个数
    39 int solve(int r){
    40     int sum = 0;
    41     //i的范围是1-2^p.size(),空集除外,每一个子集所对应的
    42     //二进制都不一样,也就是i
    43     for (int i=1; i<(1<<p.size()); ++i){
    44         int mult = 1,bits = 0;
    45         for (int j=0; j<p.size(); ++j)
    46             if (i&(1<<j)){//与i的二进制的第j位比较,看是否为1,是则选中
    47                 bits++;//计算i中1的个数,也就是质因数的个数
    48                 mult *= p[j];
    49             }
    50         int cur = r / mult;
    51         if (bits & 1)//若1的个数是奇数则进行加法,否则进行减法
    52             sum += cur;
    53         else sum -= cur;
    54     }
    55     return r - sum;//用总的数目-与n不互素的个数
    56 }
    57 int main(){
    58     init();
    59     int n,r;
    60     while(cin>>n>>r){
    61         factor(n);
    62         cout<<solve(r)<<endl;
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    自定义长时间定时器对象
    poj1326
    poj1323
    poj1218
    poj1298
    poj1276
    新年的第一场雪
    Java 语言学习总结
    假使时光能够倒转
    为了回家——春运3日战纪实
  • 原文地址:https://www.cnblogs.com/xin-hua/p/3213050.html
Copyright © 2011-2022 走看看