給定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 的方案數
這個不是很好求嗎?
所以一波莫比烏斯反演 f(
1)=∑
i=1μ
(i)g
(i)
好的,看看g(
x)怎麼直接求
現在可以取的區間範圍是l~
r 要讓g
cd是x
的倍數
區間的大小算一下,直接快速冪就行了
然後80
分到手啦
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define mod 1000000007
#define max 10000000
inline
int read()
int n,k,l,r;
bool zs[max];
int pri[max+1],tot,mu[max+1];
void pre()
}}int fpow(int a,int b)
return s;
}int g(int x,int l,int r)
int main()
現在的問題是l,
r 範圍很大
但是我們又要求乙個大的μ
怎麼辦嗷。。
非線性時間誒。
杜教篩??
我們可以搞一下
μ 的字首和就行了,
這樣兩個相減就是μ
設s(n
)=∑n
i=1μ
(i)
g(1)
s(n)
=∑i=
1n(g
∗μ)(
i)−∑
i=2n
g(i)
s(ni
) 取g
(x)=
1 s(
n)=1
−∑i=
2ns(
ni)
現在可以算出
μ 啦
再回去看一下上面寫的**
發現可以數論分塊
於是再來一次數論分塊
這題就沒啦
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define mod 1000000007
#define max 10000000
inline
int read()
int n,k,l,r;
bool zs[max];
int pri[max+1],tot,mu[max+1],smu[max+1];
map m;
void pre()
}for(int i=1;i<=max;++i)smu[i]=smu[i-1]+mu[i];
}int fpow(int a,int b)
return s;
}int smu(int x)
return m[x]=ret;
}int main()
printf("%d\n",(ans+mod)%mod);
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 數論 選數
description 我們知道,從區間 l,h l和h為整數 中選取n個整數,總共有 h l 1 n種方案。小z很好奇這樣選出的數的最大公約數的規律,他決定對每種方案選出的n個整數都求一次最大公約數,以便進一步研究。然而他很快發現工作量太大了,於是向你尋求幫助。你的任務很簡單,小z會告訴你乙個整數...
BZOJ 2301 莫比烏斯
比較裸的一道莫比烏斯入門題 具體題解網上多的是 比較簡單 不知道為什麼別人 都那麼長 沒有我的優雅哈哈哈 這題不要列舉 要分塊處理 ac includeusing namespace std typedef long long ll const ll n 1e6 ll miu n 10 v n 10...