組合數學-容斥原理-求指定區間內與n互素的數的個數
阿新 • • 發佈:2019-02-17
求指定區間內與n互素的數的個數
給出整數n和r。求區間[1,r]中與n互素的數的個數。
去解決它的逆問題,求不與n互素的數的個數。
考慮n的所有素因子pi(i=1···k)
在[1,r]中有多少數能被pi整除呢?它就是
然而,如果我們單純將所有結果,會得到錯誤答案。有些數可能被統計了多次(被好幾素因子整除,如6,在計算2時,3時就重複了)
所以我們要用容斥原理來解決。我們可以用2^k的演算法求出所有的pi的組合,然後計算每種組合的pi乘積,通過容斥原理來對結果進行加減處理。
關於此問題的最終實現
int prim[maxn]; int solve(int n,int r) { int num=0; for(int i=2;i<=sqrt(n);i++) { if(n%i==0) { prim[num++]=i; while(n%i==0) n/=i; } } if(n>1) prim[num++]=n; //對n分解素因子,num是n的素因子的個數 int sum=0; for(int msk=1;msk<(1<<num);i++) {//(1<<sum)是一個長為num的二進位制,msk通過從1到(1<<num)迴圈可以列舉這個二進位制的每一種排列情況 //msk<(1<<num)是把000··的這種排列去掉了,因為得選素因子
//二進位制排列中1表示選n該位置的的素因子,0表示不選
int mult=1; bits=0; for(int i=0;i<num;i++) { if((1<<i)&msk)//表示的是msk二進位制的第i位數字 { bits++; mult*p[i]; } } int cur=r/mult; if(bits&1) sum+=cur; else sum-=cur; } return r-sum; }
比如n的素因子的個數num=6,msk=000001,表示只選擇了n的p[0]這個素因子
msk=011001,表示選擇了n的p[0],p[3],p[4],這三個素因子。
容斥定理可以用位運算和dfs來實現