洛谷P3172 [CQOI2015]选数(容斥)

传送门

 

首先,进行如下处理

如果$L$是$K$的倍数,那么让它变成$\frac{L}{K}$,否则变成$\frac{L}{K}+1$

把$H$变成$\frac{H}{K}$

那么,现在的问题就变成了在$[L,H]$范围内选$n$个数并令他们的$gcd$为$1$的方案数

然后令$f[i]$表示选出的数最大公约数为$i$且所有数不全相同的方案数,那么设$x$为$[L,H]$之间$i$的倍数的个数,那么$f[i]=x^n-x$

然而因为这种情况求出来的只是有公约数为$i$的情况,所以还要容斥一波搞掉公约数为$2*i,3*i...$的情况,只要减一下就好了

然后如果$L$为$1$那么是可以选的所有数都是$1$的,那么答案$+1$

 1 //minamoto
 2 #include<cstdio>
 3 const int N=1e5+5,mod=1e9+7;
 4 int n,K,L,H,f[N];
 5 int ksm(int x,int y){
 6     int res=1;
 7     while(y){
 8         if(y&1) res=1ll*res*x%mod;
 9         x=1ll*x*x%mod,y>>=1;
10     }
11     return res;
12 }
13 int main(){
14 //    freopen("testdata.in","r",stdin);
15     scanf("%d%d%d%d",&n,&K,&L,&H);
16     L=L%K?L/K+1:L/K;H/=K;
17     if(L>H) return puts("0"),0;
18     for(int i=1;i<=H-L;++i){
19         int l=L,r=H;
20         l=l%i?l/i+1:l/i;r/=i;
21         if(l>r) continue;
22         f[i]=(ksm(r-l+1,n)-(r-l+1)+mod)%mod;
23     }
24     for(int i=H-L;i;--i)
25     for(int j=(i<<1);j<=H-L;j+=i)
26     f[i]=(f[i]-f[j]+mod)%mod;
27     if(L==1) (f[1]+=1)%=mod;
28     printf("%d\n",f[1]);
29     return 0;
30 }

 

posted @ 2018-09-25 16:41  bztMinamoto  阅读(259)  评论(0编辑  收藏  举报
Live2D