洛谷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 }
深深地明白自己的弱小