zoukankan      html  css  js  c++  java
  • hdu1796 how many integers can you find 二进制枚举+容斥

    题意:给定n, a1,,a2,...,am,求小于n的整数中,至少能被一个ai整除的数有多少个。数据范围:n<=2^31,m<=10,每个ai<=20

    由容斥原理,ans=Σ|ai|-Σ|ai∩aj|+Σ|ai∩aj∩ak|-...+(-1)^(m-1)|a1∩a2∩...∩am|,这儿的交意思就是取最小公倍数。注意m<=10,考虑状态压缩。最小公倍数有性质[a,b,c]=[[a,b],c],这使得多个数的最小公倍数可以依次计算。如果当前的二进制j为1,更新lcm=(lcm*a[j])/gcd(lcm,a[j]))。如果二进制中1的个数为奇数,则ans+=(n/lcm),否则ans-=(n/lcm)。注意几个点:一是输入的ai可能为0,这种情况的ai直接去掉;二是要开long long,算答案的时候有可能会爆int。然后多组数据又被坑了一波......

     1 #include<iostream>
     2 #define ll long long
     3 using namespace std;
     4 
     5 int a[20];
     6 ll n,m,i,j;
     7 
     8 ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
     9 
    10 int main(){
    11     while (cin>>n>>m){
    12       n--;int cnt=0;
    13       for (i=0;i<m;i++) {
    14         int x;cin>>x;
    15         if (x!=0) a[cnt++]=x;
    16       }
    17       ll ans=0;
    18       for (i=1;i<=(1<<cnt)-1;i++){
    19         int t=0;ll lcm=1;
    20         for (j=0;j<cnt;j++)
    21           if ((i>>j)&1){
    22               t++;
    23             lcm=(lcm*a[j])/(gcd(lcm,a[j]));
    24           }
    25          if (t%2==1) ans+=(n/lcm);else ans-=(n/lcm);
    26       }
    27       cout<<ans<<endl;
    28     }
    29     return 0;
    30 }
    hdu1796

     

  • 相关阅读:
    拦截器和过滤器区别
    sql语句查询出数据重复,取唯一数据
    bootstrap ace treeview树表
    bootstrap 时间选择器 datetime
    ajax请求后加额外的数据
    使用ajax请求,模态框调用并更改密码
    ajax get和post请求 后端接收并返回数据
    类的访问级别
    继承与组合
    类型转换函数
  • 原文地址:https://www.cnblogs.com/edmunds/p/12945453.html
Copyright © 2011-2022 走看看