The links to the two questions are given first: Http://acm.hit.edu.cn/hoj/problem/view? Id = 2576 Http://acm.hit.edu.cn/hoj/problem/view? Id = 2577
The following two questions are classic questions about the principle of rejection. I am a little blind when I am doing this, so the following expressions are not rigorous...
Hoj 2576 simple computing
My tags |
Review principle (edit) |
|
Source: Acmgroup |
|
Time Limit: 1 sec |
|
Memory limit: 32 m |
Submitted391,Accepted123
Given n integers X1 X2... XN, you shoshould 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
21 1022 203 4
Sample output
510
question:
A group of A1... an: How many data records from 1 to m can be divided by at least one of the groups
analysis:
the volume rejection principle can solve the number of mutual quality between 1-N and M. The practice is to divide m into several prime factors and then solve the problem by using the volume rejection principle. Because P1.. PK is a prime number,
gcd (PI, PJ) = 1.
This question becomes the number of N (including the sum ). Therefore, in the process of solving the problem, we have to divide it by the maximum common number. Otherwise, for example, 3, 6, and m = 18, the answer is 6. During computing, 6 and 12 are obviously divisible by 3 and 6 at the same time.
Code :
# Include <cstdio> # include <cstring> # include <iostream> # include <algorithm> using namespace STD; # define debug puts ("here") typedef 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; elsesum-= N/S;} cout <sum <Endl;} int main () {# ifndef online_judgefreopen ("suma.txt", "r", stdin); # endifint ncase, M; CIN> ncase; while (ncase --) {scanf ("% d", & size, & M); For (INT I = 0; I <size; I ++) scanf ("% d ", & di [I]); CAL (m);} return 0 ;}
Another question about Deformation
Simple computing II
My tags |
Review principle (edit) |
|
Source: Acmgroup |
|
Time Limit: 1 sec |
|
Memory limit: 32 m |
Submitted173,Accepted: 63
Given n integers X1 X2... XN, you shoshould 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
21 1022 203 4
Sample output
59
Question:
The number of N is given. Now, from 1 to m, the number can only be divisible by one of the N numbers.
Analysis:
The last question is that we can be divided by at least one of the N numbers, so we can easily solve it with rejection.
In fact, this question is equivalent to a slight deformation of the question. The result is that the question can only be divided by one of the N numbers. Intuitive
We need to remove two or more of them. Therefore, we still use the volume exclusion method, but in addition and subtraction
You just need to control it.
1. When there are only two values, the number is reduced by X 2.
2. When we add three, because we subtract two more times, we have to add them back and then subtract one of them.Part, which is exactly * 3.
3. Similarly, when you have the number of I:
I odd + S * I
I even-S * I
Code
# Include <cstdio> # include <cstring> # include <iostream> # include <algorithm> using namespace STD; # define debug puts ("here") typedef 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; elsesum-= N/S * OK;} cout <sum <Endl;} int main () {# ifndef online_judgefreopen ("suma.txt", "r", stdin); # endifint ncase, M; CIN> ncase; while (ncase --) {scanf ("% d", & size, & M); For (INT I = 0; I <size; I ++) scanf ("% d ", & di [I]); CAL (m);} return 0 ;}