1. 程式人生 > >bzoj3930[CQOI2015]選數 容斥原理

bzoj3930[CQOI2015]選數 容斥原理

最大 content mes inpu class bits put 多少 小z

3930: [CQOI2015]選數

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 1383 Solved: 669
[Submit][Status][Discuss]

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

3

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

容斥


可以註意到一個性質:任意選兩個數,這兩個數的gcd<=他們的差 易證
題目中給出的區間大小<=1e5 所以不管怎麽選,只要不全部選相同的數,gcd都會<=1e5
設f[i]為所有數的gcd為k或k的倍數的方案,易算出f[i]
假設g[i]為gcd為所有數的gcd為k的方案,可以用f[]容斥得到g[]
因為首先保證了所有方案不能選擇相同的數,所以最後特判一下能不能全部選擇K這個數來貢獻答案

順便%%用反演的大佬

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define mod 1000000007
 4
#define N 100001 5 using namespace std; 6 int M,K,L,R,fg,f[N]; 7 int quick(int a,int b){ 8 int ret=1; 9 while(b){ 10 if(b&1)ret=1ll*ret*a%mod; 11 a=1ll*a*a%mod;b>>=1; 12 } 13 return ret; 14 } 15 int main(){ 16 scanf("%d%d%d%d",&M,&K,&L,&R);fg= K<=R&&K>=L; 17 for(int i=R-L+1;i>=1;--i){ 18 int l=L/i-(L%i==0),r=R/i,t=r-l; 19 int sum=quick(t,M)-t; 20 sum<0?sum+=mod:1;f[i]=sum; 21 for(int j=i+i;j<=R-L+1;j+=i) 22 f[i]=(f[i]-f[j]+mod)%mod; 23 } 24 f[K]=(f[K]+fg)%mod;f[K]<0?f[K]+=mod:1; 25 printf("%d",f[K]); 26 return 0; 27 }

bzoj3930[CQOI2015]選數 容斥原理