Acwing---890. Divisible Numbers (Java)_Mathematics Knowledge_Principle of Exclusion

Original title link

①. Title

Insert picture description here

②. Thinking

Insert picture description here

  • Tolerance and exclusion principle formula (addition of odd numbers, subtraction of even numbers)
    Insert picture description here
  • Sample analysis
    n = 10, p1=2,p2=3, 求1-10中能满足能整除p1或p2的个数, 即2,3,4,6,8,9,10,共7个

Insert picture description here-Each set does not actually need to know what the specific elements are, as long as you know the size of the set, the size is |Si|=n/pi, for example, in the title |S1|=10/2=5,|S2|=10 /3=3

  • How to determine the size of the intersection? Because pi are all prime numbers, the product of these prime numbers is their least common multiple, n divided by this least common multiple is the size of the intersection, so |S1⋂S2|=n/(p1∗p2)=10/(2∗3)=1
  • How to code the status of each collection? The binary used here, take m = 4 as an example, so 4 binary bits are needed to indicate the selected and unselected state of each set, 1101, here means the selected set S1, S2, S4, so the number of elements in this set It is n/(p1∗p2∗p4), because the number of sets is 3, according to the formula, the previous coefficient is (−1)3−1=1. So when it comes to the current state, it should be res+=n/(p1∗p2∗p4). This can represent every state ranging from 0000 to 1111

③. Learning points

容斥原理

④. Code implementation

import java.util.Scanner;

public class Main {
    
    
	static int N=20;
	static int[] p=new int[N];
	public static void main(String[] args) {
    
    
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		for (int i = 0; i <m; i++) {
    
    
			p[i]=sc.nextInt();
		}
		int res=0;
		//枚举从1 到 1111...(m个1)的每一个集合状态, (至少选中一个集合)
		for (int i =1; i <1<<m; i++) {
    
    
			long t=1;  //选中集合对应质数的乘积
			long s=0;   //选中的集合1的数量
			
			//枚举当前状态的每一位
			for (int j = 0; j <m; j++) {
    
    
				//选中一个集合
				if((i>>j&1)==1) {
    
    
					 //乘积大于n, 则n/t = 0, 跳出这轮循环
					if(t*p[j]>n) {
    
    
						t=-1;
						break;
					}
					t*=p[j];
					s++;   //有一个1,集合数量+1
				}
			}
			if(t!=-1) {
    
    
				if(s%2==1) {
    
    
					res+=n/t; //奇数+   n/t为当前这种状态的集合数量
				}else {
    
    
					res-=n/t; //偶数-
				}
			}
		}
		System.out.println(res);
	}

}

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_45480785/article/details/114104469