zoukankan      html  css  js  c++  java
  • HOJ 2576 HOJ 2577 Simple Computing I & II 容斥原理

    两题的链接先给上:

    http://acm.hit.edu.cn/hoj/problem/view?id=2576

    http://acm.hit.edu.cn/hoj/problem/view?id=2577

    下面两题都是很经典的容斥原理的题目,自己做的时候有点瞎yy,所以下面的表达不太严谨。。。

    HOJ 2576 Simple Computing

    My Tags 容斥原理   (Edit)
      Source : ACMGroup
      Time limit : 1 sec   Memory limit : 32 M

    Submitted : 391, Accepted : 123

    Given n integers x1 x2 ... xn, you should count how many intergers from 1 to m that can be divided by at least one of them.

     Input

     The first line is an integer c which shows the number of cases. Each case contains 2 lines. The first line has 2 integers n and m. The second line contains n integers. (0<n<11, 0<m<2^31, 0<xi<100)

     Output 

    For each case print the answer in a single line.

     Sample Input

    2
    1 10
    2
    2 20
    3 4

    Sample Output

    5
    10

    题目大意:
      给出一组数a1...an,问从1到m中能有多少个数能够最少能被这组数中的一个整除

    分析:
    容斥原理可以解决1-n中与m互质的数的个数问题,做法是把m分解成几个素因子,然后利用容斥原理求解。由于p1..pk都是素数,所以
    gcd(pi,pj) == 1。
    而这题变成了n个数(包含合数)。所以在求解过程中乘完之后还得除以最大公约数。不然如3,6,m =18时,答案是6。在计算的时候,6,12很明显能够同时被3,6整除。

    代码如下:
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define debug puts("here")
    
    typedef long long ll;
    
    const int X = 105;
    
    int size;
    int di[X];
    
    int gcd(int x,int y){
    	return x==0?y:gcd(y%x,x);
    }
    
    void cal(ll n){
    	ll sum = 0;
    	for(int i=1;i<(1<<size);i++){
    		ll s = 1;
    		bool ok = false;
    		for(int j=0;j<size;j++)
    			if( i & (1<<j) ){
    				s = s/gcd(s,di[j])*di[j];
    				ok = !ok;
    			}
    		if(ok)
    			sum += n/s;
    		else
    			sum -= n/s;
    	}
    	cout<<sum<<endl;
    }
    
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("suma.txt","r",stdin);
    #endif
    	int ncase,m;
    	cin>>ncase;
    	while(ncase--){
    		scanf("%d%d",&size,&m);
    		for(int i=0;i<size;i++)
    			scanf("%d",&di[i]);
    		cal(m);
    	}
    	return 0;
    }
    

      

    另外变形的一题

    Simple Computing II

    My Tags 容斥原理   (Edit)
      Source : ACMGroup
      Time limit : 1 sec   Memory limit : 32 M

    Submitted : 173, Accepted : 63

    Given n integers x1 x2 ... xn, you should count how many intergers from 1 to m that can be divided exactly by only one of them.

    Input

    The first line is an integer c which shows the number of cases. Each case contains 2 lines. The first line has 2 integers n and m. The second line contains n integers. (0<n<11, 0<m<2^31, 0<xi<100)

    Output

    For each case print the answer in a single line.

    Sample Input

    2
    1 10
    2
    2 20
    3 4

    Sample Output

    5
    9

    题目:
      给出n个数,现在问从1到m只能够被这n个数中的一个数整除的个数

    分析:
      我们上一题是最少能够被这n个数中的一个整除,所以我们可以很容易用容斥解决掉。
      那么这题其实就相当于那题的稍微变形,求的是只能够被n个数中的一个整除。直观上
      来看,我们需要把两个或者两个以上的去掉。所以还是用容斥来做,只不过在加减的
      时候需要控制一下就好了。
      1.在只有两个的时候,减掉的个数*2。
      2.在加三的时候,由于在减二时多减了,所以我们得要加回来,然后再减掉自己那个部分,刚好是*3。
      3.同样,在拥有i个数的时候:
        i 奇数 + s*i
        i 偶数 - s*i

    代码
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define debug puts("here")
    
    typedef long long ll;
    
    const int X = 105;
    
    int size;
    int di[X];
    
    int gcd(int x,int y){
    	return x==0?y:gcd(y%x,x);
    }
    
    void cal(ll n){
    	ll sum = 0;
    	for(int i=1;i<(1<<size);i++){
    		ll s = 1;
    		int ok = 0;
    		for(int j=0;j<size;j++)
    			if( i & (1<<j) ){
    				s = s/gcd(s,di[j])*di[j];
    				ok ++;
    			}
    		if(ok&1)
    			sum += n/s*ok;
    		else
    			sum -= n/s*ok;
    	}
    	cout<<sum<<endl;
    }
    
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("suma.txt","r",stdin);
    #endif
    	int ncase,m;
    	cin>>ncase;
    	while(ncase--){
    		scanf("%d%d",&size,&m);
    		for(int i=0;i<size;i++)
    			scanf("%d",&di[i]);
    		cal(m);
    	}
    	return 0;
    }
    

      





  • 相关阅读:
    SpringBoot表单验证
    新创建的maven项目,显示的jdk版本与使用的不一致
    maven常用的构建命令
    maven 配置说明
    springmvc 初始化参数绑定(使用属性编辑器) 来处理类型转换问题
    【LOJ#10180】烽火传递 单调队列+dp
    【洛谷P1854】花店橱窗 线性dp+路径输出
    【CF1076D】Edge Deletion 最短路+贪心
    【洛谷P5020】货币系统 完全背包
    【洛谷P5018】对称二叉树
  • 原文地址:https://www.cnblogs.com/yejinru/p/2865217.html
Copyright © 2011-2022 走看看