题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1796
题目大意:
给定n和一个大小为m的集合,集合元素为非负整数。为1...n-1内能被集合里任意一个数整除的数字个数。n<=2^31,m<=10
解题思路:
容斥定理
枚举m个元素的所有非空子集,求出lcm,如果子集元素数目为偶数那就减去,否则就加上。
挑战:P296有公式
1 #include<iostream> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 10; 5 ll n, m; 6 int a[50]; 7 ll gcd(ll a, ll b) 8 { 9 return b == 0 ? a : gcd(b, a % b); 10 } 11 void solve() 12 { 13 ll ans = 0; 14 for(int i = 1; i < (1 << m); i++) 15 { 16 int num = 0; 17 for(int j = i; j != 0; j >>= 1)if(j & 1)num++;//i的二进制中1的个数 18 ll lcm = 1; 19 for(int j = 0; j < m; j++) 20 { 21 if((1 << j) & i) 22 { 23 lcm = lcm / gcd(lcm, a[j]) * a[j]; 24 if(lcm > n)break; 25 } 26 } 27 if(num&1)ans += n / lcm; 28 else ans -= n / lcm; 29 } 30 cout<<ans<<endl; 31 } 32 int main() 33 { 34 while(cin >> n >> m) 35 { 36 n--;//需要自减1,因为是1-n-1 37 int tot = 0, x; 38 for(int i = 0; i < m; i++)//可能有0元素 39 { 40 cin >> x; 41 if(x)a[tot++] = x; 42 } 43 m = tot; 44 solve(); 45 } 46 return 0; 47 }