【BZOJ】3930: [CQOI2015]选数

题目链接: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))}$


 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 1001000
10 #define llg long long 
11 #define mod 1000000007
12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
13 llg n,m,f[maxn],L,R,k;
14 
15 llg ksm(llg x,llg y)
16 {
17     llg ans=1;
18     while (y)
19     {
20         if (y&1) ans=ans*x%mod;
21         x=x*x%mod;
22         y>>=1;
23     }
24     return ans;
25 }
26 
27 int main()
28 {
29     yyj("bzoj3930");
30     cin>>n>>k>>L>>R;
31     for (llg i=R-L;i>=1;i--)
32     {
33         llg l=(L-1)/(k*i),r=R/(k*i);
34         f[i]=(ksm(r-l,n)-(r-l)+mod) %mod;
35         for (llg j=2;i*j<=R-L;j++)
36         {
37             f[i]=f[i]-f[i*j]+mod;
38             f[i]%=mod;
39         }
40     } 
41     if (L<=k && k<=R) f[1]++;
42     cout<<f[1];
43     return 0;
44 }

 

posted @ 2017-02-12 21:11  №〓→龙光←  阅读(120)  评论(0编辑  收藏  举报