洛谷P3172 [CQOI2015]选数

Description

我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案。小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究。然而他很快发现工作量太大了,于是向你寻求帮助。你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个。由于方案数较大,你只需要输出其除以1000000007的余数即可。


Input

输入一行,包含4个空格分开的正整数,依次为N,K,L和H。


Output

输出一个整数,为所求方案数。


Solution

这里有两种做法,一种是递推:
我们考虑最大公约数为k*i的方案数,表示为f[i]。
明显应有 1 ≤ i ≤ h − l 1\leq i\leq h-l 1ihl
否则只有一种 x , x , x , x , x , . . . ( i ∣ x ) x,x,x,x,x,...(i|x) x,x,x,x,x,...(ix)的方案,此时最大公约数为x而非i,不予考虑。
设H=(h-1)/k+1,L=(l-1)/k+1
同样的,计算过程中要去掉这种部分,所以减去H-L+1
那么 f [ i ] = ( H − L + 1 ) n − ( H − L + 1 ) − ∑ a ≥ 2 k ∗ i ∗ a ≤ h − l f [ k ∗ i ∗ a ] f[i]=(H-L+1)^n-(H-L+1)-\sum_{a\geq2}^{k*i*a\leq h-l}f[k*i*a] f[i]=(HL+1)n(HL+1)a2kiahlf[kia]
从大到小递推即可。

第二种,莫比乌斯反演+杜教筛
在这里插入图片描述
中xi表示第i个数的取值。

然后这里就可以分块来求。

由于h的范围过大,所以需要使用杜教筛求mu的前缀和,详见 bzoj3944


Code

只有第一种 不会杜教筛

#include<bits/stdc++.h>
#define mod 1000000007
#define maxn 100000
using namespace std;
long long f[maxn+1];
long long qvod(long long x,long long k){
	long long ans=1;
    while(k!=0){
        if(k&1)ans=ans*x%mod;
        x=x*x%mod;
        k>>=1;
	}
	return ans;
}
int main(){
	int a,b,k,n;
	scanf("%d%d%d%d",&n,&k,&a,&b);
	int l=a/k,r=b/k;
	if(a%k)l++;
	for(int i=maxn;i>=1;i--){
		int L=l/i,R=r/i;
		if(l%i) L++;
		if(l<=r){
			f[i]=qvod(R-L+1,n);
			f[i]=(f[i]-(R-L+1)+mod)%mod;
			for(int j=i*2;j<=maxn;j+=i)
			f[i]=(f[i]-f[j]+mod)%mod;
		}
	}
	if(l==1) f[1]++;
	printf("%lld",(f[1]+mod)%mod);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值