hdu 4135 容斥原理

2021-06-27 05:49:09 字數 1196 閱讀 7630

題意:就是讓你求(a,b)區間於n互質的數的個數.

分析:我們可以先轉化下:用(1,b)區間與n互質的數的個數減去(1,a-1)區間與n互質的數的個數,那麼現在就轉化成求(1,m)區間於n互質的數的個數,如果要求的是(1,n)區間與n互質的數的個數的話,我們直接求出n的尤拉函式值即可,可是這裡是行不通的!我們不妨換一種思路:就是求出(1,m)區間與n不互質的數的個數,假設為num,那麼我們的答案就是:m-num!現在的關鍵就是:怎樣用一種最快的方法求出(1,m)區間與n不互質的數的個數?方法實現:我們先求出n的質因子(因為任何乙個數都可以分解成若干個質數相乘的),如何盡快地求出n的質因子呢?我們這裡又涉及兩個好的演算法了!第乙個:用於每次只能求出乙個數的質因子,適用於題目中給的n的個數不是很多,但是n又特別大的;(第二個:一次求出1~n的所有數的質因子,適用於題目中給的n個數比較多的,但是n不是很大的。(本題適用第乙個演算法!舉一組例項吧:假設m=12,n=30.

第一步:求出n的質因子:2,3,5;

第二步:(1,m)中是n的因子的倍數當然就不互質了(2,4,6,8,10)->n/2  6個,(3,6,9,12)->n/3  4個,(5,10)->n/5  2個。

如果是粗心的同學就把它們全部加起來就是:6+4+2=12個了,那你就大錯特錯了,裡面明顯出現了重複的,我們現在要處理的就是如何去掉那些重複的了!

第三步:這裡就需要用到容斥原理了,公式就是:n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(2*3*5).

第四步:我們該如何實現呢?我在網上看到有幾種實現方法:dfs(深搜),佇列陣列,位運算三種方法都可以!上述公式有乙個特點:n除以奇數個數相乘的時候是加,n除以偶數個數相乘的時候是減。我這裡就寫下用佇列陣列如何實現吧:我們可以把第乙個元素設為-1然後具體看**如何實現吧!

同種型別的題目:hdu 2841    hdu1695

**實現:

#include#includeusing namespace std;

__int64 a[1000],num;

void init(__int64 n)//求乙個數的質因子

}if(n>1)//這裡要記得

a[num++]=n;

}__int64 haha(__int64 m)//用佇列陣列實現容斥原理

{ __int64 que[10000],i,j,k,t=0,sum=0;

que[t++]=-1;

for(i=0;i

hdu4135 容斥原理

題意 給出a,b,n,求出 a,b 範圍內與n互素的數字的個數。即b範圍內的不與n互素的數減去a範圍內不與n互素的數,把 1,a 1,b 中不與n互素的數分別求出來,再減掉就是和n互素的數了。那麼首先將n分解質因數,因子和因子的倍數可以被除盡,一定不與n互素,把這些數都記下來,篩法求素數即可 然後把...

hdu 4135 容斥原理

剛接觸,有關因子個數的增加不太弄得好,然後看到了這個神奇的遞迴 ac include includeusing namespace std define ll long long ll a,b,ansa,ansb,ans,p 100 up void dfs int n,bool tag,ll num...

hdu 4135,數學 容斥

題意 求 a,b 區間裡面,與c互質的數的個數。範圍 0分析 先將c分解質因數,根據c的範圍可以判斷質數的範圍不超過x個。x 自己線性篩素數後,從小到大乘一下,看當乘到多少個的時候,積大於10 9,則可以判斷c的最多質因數個數 假設c的質因數有2,3,5 則 a,b 區間裡,包含質因數2的數的個數為...