1. 程式人生 > >HDU-1796 How many integers can you find(容斥定理和二進位制的運用)

HDU-1796 How many integers can you find(容斥定理和二進位制的運用)

HDU-1796 How many integers can you find

題意:

有多組輸入,第一行為n和m,第二行為m個數字。要求統計小於n的數字中有多少個能被第二行中的m個數字整除。
注意!第二行的輸入中可能為零,所以要注意輸入時只有大於零的數被允許。

思路:

看到這樣要求有多少個數字能被整除的題目,我一般會想到容斥定理。但是第二行中的數字最多能達到十個,此時直接十進位制運算運用容斥定理可能很複雜。如果我們利用二進位制運算的特點進行求最小公倍數的運算就能方便許多。因為在計算交集時要重複許多步,利用位運算子&就能判斷是求幾次,例如,3的二進位制是11,此時就能求的交集是與之對應的1的1和2的10。

AC程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int SIZE = 100;
int arr[SIZE];
long long gcd(long long x, long long y) {
    return y == 0 ? x : gcd(y, x%y);
}
long long lcm(long long x, long long y) {
    return x/gcd(x, y)*y;
}
int main() {
    int
n, m; while(scanf("%d%d", &n, &m) != EOF) { memset(arr, 0, sizeof(arr)); n--; long long sum = 0; int shu = 0; for(int i = 0; i < m; i++) { int temp; scanf("%d", &temp); if(temp > 0) { arr[shu] = temp; shu++; } } for
(int i = 1; i < (1 << shu); i++) { int js = 0, tmp = 1; for(int j = 0; j < shu; j++) { if(i & (1 << j)) { js++; tmp = lcm(tmp, arr[j]); } } if(js%2) { sum += n/tmp; } else { sum -= n/tmp; } } printf("%lld\n", sum); } return 0; }