http://www.lydsy.com/JudgeOnline/problem.php?id=3930 (题目链接)
题意
求在${[L,R]}$中选出${n}$个数,可以相同,使得它们的${gcd=K}$的方案数。
Solution
首先,我们有一个性质:如果选出来的数不全相同,那么它们的${gcd}$不会超过选出来的最大数与最小数之差。
为什么是这样呢,更相减损术嘛。
所以就好做咯,枚举gcd,然后瞎搞搞,最后再把全部选一个数的方案加上就好了。
代码
// bzoj3930
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 2147483640
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
const int maxn=100010;
LL f[maxn];
int n,K,L,R;
LL power(LL a,LL b) {
LL res=1;
while (b) {
if (b&1) (res*=a)%=MOD;
b>>=1;(a*=a)%=MOD;
}
return res;
}
int main() {
scanf("%d%d%d%d",&n,&K,&L,&R);
for (int i=R-L;i>=1;i--) if (i%K==0) {
int l=(L-1)/i,r=R/i;
f[i]=power(r-l,n)-(r-l);
for (int j=2;i*j<=R-L;j++)
f[i]=(f[i]-f[i*j]+MOD)%MOD;
}
if (K>=L && K<=R) (++f[K])%=MOD;
printf("%lld",f[K]);
return 0;
}