Hdu--1796(数论,容斥原理)

2014-09-05 01:01:28

How many integers can you find

Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4202    Accepted Submission(s): 1196


Problem Description
  Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N=12, and M-integer set is {2,3}, so there is another set {2,3,4,6,8,9,10}, all the integers of the set can be divided exactly by 2 or 3. As a result, you just output the number 7.

 

Input
  There are a lot of cases. For each case, the first line contains two integers N and M. The follow line contains the M integers, and all of them are different from each other. 0<N<2^31,0<M<=10, and the M integer are non-negative and won’t exceed 20.
 
Output
  For each case, output the number.

 

Sample Input
12 2
2 3
 
Sample Output
7

 

思路:经典的容斥原理,枚举+容斥,(任1个数的公倍数) - (任2个数的公倍数) + (任3个数的公倍数)。。。。。

 1 /*************************************************************************
 2     > File Name: hdu1796.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Thu 04 Sep 2014 09:53:53 PM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 int Gcd(int a,int b) { return b == 0 ? a : Gcd(b,a % b); }
16 int Lcm(int a,int b) { return a / Gcd(a,b) * b; }
17 
18 int n,m;
19 int v[15];
20 int ans;
21 
22 void Dfs(int p,int cnt,int l,int tar){
23     if(p > m){
24         //printf("l : %d,tar : %d\n",l,tar);
25         if(cnt == tar){
26             int tmp = (n - 1) / l;
27             ans += (tar & 1) ? tmp : -tmp;
28         }
29         return;
30     }
31     if(m - p + 1 + cnt < tar)
32         return;
33     Dfs(p + 1,cnt,l,tar);
34     int tl = Lcm(l,v[p]);
35     if(tl < n && cnt < tar)
36         Dfs(p + 1,cnt + 1,tl,tar);
37 }
38 
39 int main(){
40     while(scanf("%d %d",&n,&m) != EOF){
41         for(int i = 1; i <= m; ++i){
42             scanf("%d",&v[i]);
43             if(!v[i]) --i,--m;
44         }
45         ans = 0;
46         for(int i = 1; i <= m; ++i)
47             Dfs(1,0,1,i);
48         printf("%d\n",ans);
49     }
50     return 0;
51 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/3957132.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值