The question was thrown into the trap by the person who asked the question, and the question was wrong .. Well, I don't want to say much.
Question: give two groups of numbers. Group A is the lucky base, and group B is the unlucky base. Ask How many numbers are there in the [low, high] range: is divided by at least a number in group A, andNoBeing BArbitraryDivision by number. | A | <= 15.
Analysis: if the length of a is so small and the number of conditions that can be satisfied in the interval is found, it is easy to think of the rejection principle because it is not divisible by any number in B, therefore, if we take all the numbers in array B as a minimum public multiple LCM, the lucky number will not be divisible by this LCM.
Then enumerate the subset to remove the elements in a from each other. For example, if a = [2, 4], the elements in a can be divisible by at least one number, then a value of 2 can be satisfied, and 4 is removed.
Set a1 = {number of segments divided by a1}, a2 = {number of segments divided by a2},... an = {number of segments divided by}
Because :,
Then, we need to handle the case that the data is not divisible by LCM. If we set Bi = {the number of segments divisible by I}, the number to be subtracted is:
(CNT count)
Therefore, we can reject it.
The number of K divisible numbers in a range [low, high] is: High/K-(low-1)/K
Pay attention to handling long bursts.
Code: (0 ms)
# Include <iostream> # include <cstdio> # include <cstring> # include <cmath> # include <algorithm> # define ll long longusing namespace STD; # define n Limit 7ll A [17], AA [17]; LL B [504]; int vis [17]; ll gcd (ll a, LL B) {If (! B) return a; return gcd (B, A % B);} int calc (INT s) // The number of computations {int CNT = 0; while (s) {If (S & 1) CNT ++; s >>= 1 ;}return CNT ;}int main () {int n, m, I, j; ll low, high; ll CNT; int s; while (scanf ("% d % LLD", & N, & M, & low, & High )! = EOF) {If (n = 0 & M = 0 & Low = 0 & high = 0) break; for (I = 0; I <n; I ++) scanf ("% LLD", & A [I]); for (I = 0; I <m; I ++) scanf ("% LLD", & B [I]); memset (VIS, 0, sizeof (VIS); sort (A, A + n ); for (I = 0; I <n; I ++) {If (vis [I]) continue; For (j = I + 1; j <n; j ++) {If (vis [J]) continue; if (a [J] % A [I] = 0) // remove redundancy vis [J] = 1 ;}} int Ka = 0; for (I = 0; I <n; I ++) {If (! Vis [I]) AA [Ka ++] = A [I];} ll LCM = 1ll; int tag = 1; for (I = 0; I <m; I ++) // calculate LCM {LCM = LCM * B [I]/(gcd (LCM, B [I]); if (LCM> high | LCM <0) {tag = 0; break ;}} if (! Tag) // burst, regardless of LCM = high + 1; S = (1 <ka)-1; // Total number of States ll ans = 0; for (INT state = 1; State <= s; State ++) {int c = calc (State); int Sign = (C % 2? 1ll:-1ll); // set the symbol int TMP = state based on the number; I = 0; ll antibase = 1ll; ll base = 1ll; int flag = 1; while (I <ka) // subset {If (TMP & 1) {base = base/gcd (base, AA [I]) * AA [I]; if (base> high | base <0) {flag = 0; break ;}} TMP >>= 1; I ++ ;}if (! Flag) continue; ans + = sign * (high/base-(low-1LL)/base); If (! Tag) // LCM burst range, regardless of continue; antibase = base/(gcd (base, LCM) * LCM; ANS-= sign * (high/antibase-(low-1LL) /antibase);} printf ("% LLD \ n", ANS);} return 0 ;}
View code
(If any error is found, please comment it out)
Zoj 3233 lucky number-Principle of rejection