【bzoj3930】 CQOI2015—选数

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;
}

 

posted @ 2017-02-12 10:37  MashiroSky  阅读(232)  评论(2编辑  收藏  举报