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 4sample 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...