解题:CQOI 2015 选数

题面

神仙题,不需要反演

首先上下界同时除以$k$,转换成取$n$个$gcd$为$1$的数的方案数,其中上界向下取整,下界向上取整

然后设$f[i]$表示选$n$个互不相同的数$gcd$为$i$的方案数,这么设是为了容斥,然后就可以直接求出来$f[i]=m^n-m$,其中m是$i$倍数的个数

同时从大到小容斥就可以了

 1 #include<cstdio>
 2 #include<vector> 
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int mod=1e9+7;
 7 int n,k,l,r,ln,ans[100005];
 8 int Qpow(int x,int k)
 9 {
10     if(k==1) return x;
11     int tmp=Qpow(x,k/2);
12     return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
13 }
14 int main()
15 {
16     scanf("%d%d%d%d",&n,&k,&l,&r);
17     l=(l+k-1)/k,r/=k,ln=r-l;
18     for(int i=ln;i;i--)
19     {
20         int ll=(l+i-1)/i,rr=r/i,len=rr-ll+1;
21         ans[i]=(Qpow(len,n)-len+mod)%mod;
22         for(int j=i*2;j<=ln;j+=i)
23             ans[i]=(ans[i]-ans[j]+mod)%mod;
24     }
25     printf("%d",ans[1]+(l==1));
26     return 0;
27 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10251868.html