HDU 2204 容斥原理(過程詳解)

2021-08-28 02:57:10 字數 3265 閱讀 9192

input

本題有多組測試資料,每組包含乙個整數n,1<=n<=1000000000000000000(10^18). 

output

對於每組輸入,請輸出在在1到n之間形式如m^k的數的總數。 

每組輸出佔一行。 

sample input

10

361000000000000000000

sample output

4

91001003332

哎,一開始學容斥,並不知道怎麼用上去,**寫起來好寫,但是思路難啊。

下面開始分析:

題目意思:給你乙個n,求出1-n裡面,構成m^k(k>1)的數,比如1-4裡面有1,4兩個,1一定可以。

然後我們就去看資料範圍了,1e18,很大,不可能列舉。

接著我就想,能不能分一下類,按2^k,  3^k,  4^k.......,這種,但是一想,1e18開方也還有1e9,這樣分類不行

隨後我就按照指數來分類,指數相同歸為一類,例如(2^2, 3^2, 4^2....)歸為一類,(2^3, 3^3, 4^3)歸為一類,一次類推。

而且,這樣分類還可以算出這一類有多少個數, 直接乙個公式就行了,就是開k次方,然後-1,因為是從2開始的

某一類的個數

其實這個特別好推。

重要的是下面的:去重

我們分析一下,如果不去重,只需要一直開方,直到不能開為止,然後答案累加,這樣複雜度並不高,1e18次最多開60次方就沒了,因為2^60=1e18,所以時間根本不用擔心。

那麼怎麼去重呢,拿樣例36來說,我們先列舉出來

指數為2:2^2    3^2      4^2     5^2      6^2

指數為3:2^3    3^3

指數為4:2^4

指數為5:2^5

後面就沒了

我們可以看到16這個數重複了,4^2 = 16,     2^4 = 16

這是因為指數4本來就是2的倍數,2^4 = ( 2^2 )^2

那如果我們指數只列舉質數,是不是就能避免這種情況了,而且又可以減小計算量

但是,稍微再列舉一下,又能發現問題,

像 27^2這種   27^2 = ( 3*3*3 )^2 = 3^(3*2) = 3^6 = 9^3

你雖然避免了3^6,但是還有9^3會重複。

這時候就是最難點了,需要用到容斥,個人感覺在這個最後一點上不好想

27^2 和 9^3之所以會重複,是因為它們都有乙個6,就是都能湊出指數6,那麼我們減去指數6所得到的個數,就是答案了。

再自己乙個樣例

n = 729

729 = 27^2 = 3^6

指數為2:2^2    3^2      4^2     5^2      6^2     7^2     8^2     9^2............................27^2

指數為3:2^3    3^3      4^3     5^3      6^3    7^3      8^3     9^3

指數為5:2^5

指數為7:2^7 

後面沒有了

這裡,我們就挑指數為2和指數為3的兩類進行分析,看如何去除重複

我們首先要知道,指數為2和3的,重複的數一定可以構成指數為6的數

有 8^2 和  4^3是重複的

然後我們用n算出指數為6的個數,是1個,那麼在算指數為2和3時,先+指數為2的,在+指數為3的,最後--指數為6的,這就用到了容斥原理。

所以我們開始設計演算法:

①首先,我們把n的質指數求出來,質指數就是指數為質數,乙個迴圈就可以搞定,而且非常快,幾下就沒了,前面分析過,就是一直開方,開到不能開為止,那麼我們就把指數記錄了下來。

②指數記錄下來了,就要用容斥了,個人習慣用dfs,簡潔一些,這時候我們還需要設計乙個函式,給你乙個指數值,你能算出這個符合這個指數的答案有多少個

需要注意一點,如果用dfs寫,需要加乙個條件,就是因子乘積小於60,不然就會超時,因為乙個很大的數得出來的指數還是挺多的,指數組合在一起也挺多,但是很多組合都沒有用,因為2^60 > 1e18,或者你加乙個條件,因子最多選3個,不能選多了

#include#include#include#include#include#include#include#include#include#define fori(l,r) for( int i = l ; i <= r ; i++ )

#define forj(l,r) for( int j = l ; j <= r ; j++ )

#define mem(a,val) memset(a,val,sizeof a)

#define inf 0x3f3f3f3f

#define longinf 0x3f3f3f3f3f3f3f3f

using namespace std;

#define eps 1e-7

typedef long long ll;

const int maxn = 1e3+4;

bool isprime[maxn];

double prime[maxn];

int primecnt;

double n;

ll ans;

ll a[maxn];

int cnt;

void getprime()

ll f( double x )

void dfs( int start,int times,int goal,double val )

for( int i = start ; i < cnt ; i++ )

dfs(i+1,times+1,goal,val*a[i]);

}int main()

fori(1,cnt-1)

dfs(1,0,i,1);

printf("%lld\n",ans+1);

}return 0;}/*

16 4

2 5 6 9

19 3

2 3 4

*/

hdu 2204 容斥原理

感覺斷斷續續的看了好久的容斥 然後還是看不懂莫比烏斯反演 以後基本原理懂了就先上手做題吧,不然感覺還是不會還浪費時間 第一題容斥 題意 給你乙個數n 1,10 18 叫你求n內有多少個數是m k得來的。可知 m k都可以變成乙個冪數為素數的形式,所以可以列舉素數,求每個素數滿足的個數。因為存在 形如...

HDU 2204(容斥原理)

input 本題有多組測試資料,每組包含乙個整數n,1 n 1000000000000000000 10 18 output 對於每組輸入,請輸出在在1到n之間形式如m k的數的總數。每組輸出佔一行。sample input 10 361000000000000000000 sample outpu...

hdu2204 容斥原理)

容斥原理 設a ia i ai 為集合,ai a i ai 為集合大小 則 a1 a2 a3 a 4 an a 1 cup a 2 cup a 3 cup a 4 cdots a n a1 a 2 a 3 a 4 a n i 1n ai i 1 n j i 1n ai aj i 1 n j i 1n...