Light OJ 1117 Helping Cicada(容斥+二进制枚举)

Cicada is an insect with large transparent eyes and well-veined wings similar to the “jar flies”. The insects are thought to have evolved 1.8 million years ago during the Pleistocene epoch. There are about 2,500 species of cicada around the world which live in temperate tropical climates.

These are all sucking insects, which pierce plants with their pointy mouthparts and suck out the juices. But there are some predators (like birds, the Cicada Killer Wasp) that attack cicadas. Each of the predators has a periodic cycle of attacking Cicadas. For example, birds attack them every three years; wasps attack them every 2 years. So, if Cicadas come in the 12th year, then birds or wasps can attack them. If they come out in the 7th year then no one will attack them.

So, at first they will choose a number N which represents possible life-time. Then there will be an integer M indicating the total number of predators. The next M integers represent the life-cycle of each predator. The numbers in the range from 1 to N which are not divisible by any of those M life-cycles numbers will be considered for cicada’s safe-emerge year. And you want to help them.

Input 
Input starts with an integer T (≤ 125), denoting the number of test cases.

Each case contains two integers N (1 ≤ N < 231) and M (1 ≤ M ≤ 15). The next line contains M positive integers (fits into 32 bit signed integer) denoting the life cycles of the predators.

Output 
For each test case, print the case number and the number of safe-emerge days for cicada.

Sample Input 

15 3 
2 3 5 
10 4 
2 4 5 7 
Sample Output 
Case 1: 4 
Case 2: 3

题意:
给出数m和n个数,问<=m的所有中有多少个数不是这n个数(n个数任意选取)的倍数。m<=15

思路:

我们求<=m的数是这n个数倍数的个数。
对于单个的数来说,m/a[i]即为答案,对于x个数来说,n/(x给数 的最小公倍数)即为答案,但此题要求是这n个数的任意组合,这就需要容斥原理。AUBUC=A+B+C-A∩B-A∩C-B∩C-A∩B∩C(奇加偶减)

因为n<=15,所以进行二进制枚举。

#include   
#include   
#include 
#define N 1005  
using namespace std;
const int MOD=10056;
typedef long long ll;
ll gcd(ll a,ll b)
{
  return b?gcd(b,a%b):a;
}
ll lcm(ll a, ll b)
{
	ll t=gcd(a,b);
	return a/t*b;
}
//ll gcd(ll a,ll b) { return b == 0 ? a : gcd(b, a % b); }
ll a[20];
int main()  
{  
     
	int T;
	scanf("%d",&T);
	int k=1;

    while(T--)  
    {  
    	ll m;
    	int n;
    	scanf("%lld%d",&m,&n);
	    for(int i=0;i

 

你可能感兴趣的:(算法基础——二进制枚举,数学----数论)