bzoj3930 數論 選數

2021-08-19 03:14:09 字數 1467 閱讀 8300

description

我們知道,從區間[l,h](l和h為整數)中選取n個整數,總共有(h-l+1)^n種方案。小z很好奇這樣選出的數的最大公約數的規律,他決定對每種方案選出的n個整數都求一次最大公約數,以便進一步研究。然而他很快發現工作量太大了,於是向你尋求幫助。你的任務很簡單,小z會告訴你乙個整數k,你需要回答他最大公約數剛好為k的選取方案有多少個。由於方案數較大,你只需要輸出其除以1000000007的餘數即可。

input

輸入一行,包含4個空格分開的正整數,依次為n,k,l和h。

output

輸出乙個整數,為所求方案數。

sample input

2 2 2 4

sample output

hint

樣例解釋

所有可能的選擇方案:(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4,

3), (4, 4)

其中最大公約數等於2的只有3組:(2, 2), (2, 4), (4, 2)

對於100%的資料,1≤n,k≤10^9,1≤l≤h≤10^9,h-l≤10^5

題解

數學太差不如退役

唉被數學題艹飛了。。全程%hanks_o進隊爺

學到了乙個優秀的思想

設f[i]表示組合內不全部重複的最大公約數為i的數量

對於乙個數i,我們可以算出他的的f[i*2],f[i*3],f[i*4]…,然後把i的總答案算出來,再減去f[i*2],f[i*3]…

那麼對於這道題,可以先把範圍全部/k,然後就相當於找最大公約數為1的數量了

和上面一樣地dp容斥即可

注意在選的時候可能選出全部相同的組合,那麼對於這些組合我們是要減去的。

特判一下1的情況,1是可選的

#include

#include

#include

#include

#include

using namespace std;

typedef long long ll;

const ll mod=1000000007;

ll n,k,l,r;

ll pow_mod(ll a,int b)

return ret;

}ll f[110000];

int main()

}if(l==1)f[1]++;f[1]%=mod;

printf("%lld\n",f[1]);

return

0;}

bzoj3930 選數 遞推

看了一下popoqqq爺的莫比烏斯反演,果斷棄療。還是寫遞推好,又短又快。令f i 表示當數不全相等時 為什麼如此,後面再說 最小公倍數為i k的方案,那麼 首先,當公倍數 注意不是最小 為i k時,總方案數x n x,其中x表示l r中i k的倍數,再減去重複的方案 u 2,i k u r l f...

BZOJ3930 選數(莫比烏斯反演,杜教篩)

給定n,k,l,r 問從l r中選出 n 個數,使得他們gc d k的方案數 這樣想,既然gc d k 首先就把區間縮小一下 這樣變成了gc d 1 設f i 表示gc d 恰好為 i 的方案數 那麼,要求的是f 1 設g x d x f d 所以g x 表示x gcd 的方案數 這個不是很好求嗎?...

bzoj 2734 集合選數

構造矩陣 1 3 9 27 2 6 18 54 4 12 36 108 每個數是上面的數乘2,左面的數乘3。這樣進行狀壓dp就是相鄰的格仔不能選的方案數。如何判斷乙個二進位制數沒有兩個連續的1?x x 1 0 如果有的數沒有出現過,就以它為左上角元素再構造乙個矩陣。這是怎麼想到的?include i...