您的位置:首页 > 其它

【BZOJ】3930: [CQOI2015]选数

2017-02-12 21:11 295 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3930

求从${l~r}$中选$n$个数,最大公约数为$k$的方案数。

$gcd$?一开始就往莫比乌斯反演上面想,考虑一下如选两个数是什么样子的。

${\sum _{i=L}^{R}\sum _{j=L}^{R}\left [ gcd(i,j)=k \right ]}$

${=\sum _{i=\left \lfloor \frac{L}{K} \right \rfloor}^{\left \lfloor \frac{R}{K} \right \rfloor}\sum _{j=\left \lfloor \frac{L}{K} \right \rfloor}^{\left \lfloor \frac{R}{K} \right \rfloor}\left [ gcd(i,j)=1 \right ]}$

${=\sum _{i=\left \lfloor \frac{L}{K} \right \rfloor}^{\left \lfloor \frac{R}{K} \right \rfloor}\sum _{j=\left \lfloor \frac{L}{K} \right \rfloor}^{\left \lfloor \frac{R}{K} \right \rfloor}\sum _{d|gcd(i,j)}\mu(d)}$

${=\sum_{d=1}^{\left \lfloor \frac{R}{K} \right \rfloor}\mu (d)(\left \lfloor \frac{R}{Kd} \right \rfloor-\left \lfloor \frac{L-1}{Kd} \right \rfloor)^{2}}$

同理的,如果是选$n$个数:

$${\sum_{d=1}^{\left \lfloor \frac{R}{K} \right \rfloor}\mu (d)(\left \lfloor \frac{R}{Kd} \right \rfloor-\left \lfloor \frac{L-1}{Kd} \right \rfloor)^{n}}$$

接下来线性筛,分块直接算即可。

但是

  MDZZ,${R-L<=1e5}$的这个条件没用到,嗯这个范围应该是个${log^{1e5}}$。

  令$f[i]$表示$gcd=i$的方案数,${A\left \lceil \frac{L}{K} \right \rceil}$,${B=\left \lfloor \frac{R}{K} \right \rfloor}$。

  转移为:$${f[i]=(r-l+1)^{n}-t-\sum _{i|j}f[j]}$$

  枚举$i$,$j$,其中$j$是调和级数的意义,复杂度${O(nlog(R-L))}$

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 1001000
#define llg long long
#define mod 1000000007
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,f[maxn],L,R,k;

llg ksm(llg x,llg y)
{
llg ans=1;
while (y)
{
if (y&1) ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans;
}

int main()
{
yyj("bzoj3930");
cin>>n>>k>>L>>R;
for (llg i=R-L;i>=1;i--)
{
llg l=(L-1)/(k*i),r=R/(k*i);
f[i]=(ksm(r-l,n)-(r-l)+mod) %mod;
for (llg j=2;i*j<=R-L;j++)
{
f[i]=f[i]-f[i*j]+mod;
f[i]%=mod;
}
}
if (L<=k && k<=R) f[1]++;
cout<<f[1];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: