Luogu P3172 [CQOI2015]选数
Posted cjjsb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P3172 [CQOI2015]选数相关的知识,希望对你有一定的参考价值。
这题的反演做法好像很不可食用啊还得套一个杜教筛
我们注意到题目一个重要的性质:(H-Lle10^5),看起来可以好好利用一下。
我们首先转化问题,类似于许多和(gcd)有关的问题,我们将原来的最大公约数(K)想办法变成(1)
这个怎么处理呢,其实很简单,将(L)变为(lceil frac{L}{K} ceil),将(R)变为(lfloorfrac{H}{K} floor)。
显然这样我们把问题转化为:在([L,H])种取(N)次数使它们的(gcd)为(1)
然后我们考虑计算一个(f_i),表示选出的数的(gcd)为(i),且选出的所有数不全相同的方案数。
那么我们借Luogu P1447 [NOI2010]能量采集的思路,考虑容斥计算(f_i)
我们首先求出([L,H])之间(i)的倍数(x),那么先令(f_i=x^N-x)
但是发现这样的方案只是含有公约数,因此我们还要减去(f_{ki}(kin N^+,k>1))的答案
然后做法很明显了,倒序枚举并计算即可,复杂度根据调和级数公式为(O(n(ln(n)+H_n)))
还有注意一下(L=1)时所有的数都可以选(1),因此要特判。
CODE
#include<cstdio>
#define RI register int
using namespace std;
const int N=100005,mod=1000000007;
int n,k,L,R,l,r,f[N];
inline void dec(int &x,int y)
{
if ((x-=y)<0) x+=mod;
}
inline int quick_pow(int x,int p,int mul=1)
{
for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
int main()
{
RI i,j; scanf("%d%d%d%d",&n,&k,&L,&R);
L=L%k?L/k+1:L/k; R=R/k; for (i=1;i<=R-L;++i)
{
int l=L%i?L/i+1:L/i,r=R/i;
f[i]=quick_pow(r-l+1,n); dec(f[i],r-l+1);
}
for (i=R-L;i;--i) for (j=i<<1;j<=R-L;j+=i) dec(f[i],f[j]);
return printf("%d",L^1?f[1]:(f[1]+1)%mod),0;
}
以上是关于Luogu P3172 [CQOI2015]选数的主要内容,如果未能解决你的问题,请参考以下文章