差不多是条咸鱼了…………
一开始对着题目yy了一个貌似很正确,复杂度不会算的搜索,想了想不是很敢打,往DP想,然后想出了一个看起来很正确的DP,然后挂了….
那想容斥咯………..不会………
那试试反演咯…………..还是不会………
那我到底会什么…………..
看题解好像还是会的
这题做法好多的样子,主要是两类,一类是反演,Orz PoPoQQQ
μ
的前缀和处理窝看不懂…………还有一类是容斥,因为区间里选n个不是全部一样的数,有一个易证的结论:他们的gcd不会超过区间长度,
所以现将区间缩为
最后要加上全部选一样的数对答案的贡献,那么只有K在可以选择的区间内时才会产生1的贡献
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 100010;
const ll Mod = 1e9+7;
ll pw(ll x,int k)
{
x%=Mod;ll ret=1;
for(ll t=x;k;k>>=1,t=t*t%Mod)
if(k&1)ret=ret*t%Mod;
return ret;
}
ll f[maxn];
int n,K,L,H;
int main()
{
scanf("%d%d%d%d",&n,&K,&L,&H);
int l=L/K,r=H/K;
if(L%K) l++;
int N=r-l+1;
for(int i=N;i>=1;i--)
{
int tr=r/i,tl=l/i;
if(l%i)tl++;
if(tl<=tr)
{
f[i]=pw(tr-tl+1,n);
f[i]-=tr-tl+1;
for(int j=2*i;j<=N;j+=i) f[i]-=f[j];
f[i]=(f[i]%Mod+Mod)%Mod;
}
}
if(l<=1&&l<=r) f[1]=(f[1]+1)%Mod;
printf("%lld\n",f[1]);
return 0;
}