莫比乌斯反演+杜教筛。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #define maxn 10000000 #define mod 1000000007 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; long long n,k,l,r,miu[maxn+50],prime[maxn+50],top=0,ans=0; bool vis[maxn+50]; map <long long,long long> mp; void linear_shaker() { miu[1]=1; for (long long i=2;i<=maxn;i++) { if (!vis[i]) { prime[++top]=i; miu[i]=-1; } for (long long j=1;j<=top && i*prime[j]<=maxn;j++) { vis[i*prime[j]]=true; if (i%prime[j]==0) { miu[i*prime[j]]=0; break; } else miu[i*prime[j]]=-miu[i]; } } for (long long i=1;i<=maxn;i++) miu[i]+=miu[i-1]; } long long f_pow(long long a,long long b) { long long base=a,ans=1; while (b) { if (b&1) ans=(ans*base)%mod; base=(base*base)%mod; b>>=1; } return ans; } long long ask(long long x) { if (x<=maxn) return miu[x]; if (mp.find(x)!=mp.end()) return mp[x]; long long pos=2,last=1,ret=0; while (pos<=x) { last=x/(x/pos); ret+=(last-pos+1)*ask(x/pos); pos=last+1; } return mp[x]=1-ret; } int main() { scanf("%lld%lld%lld%lld",&n,&k,&l,&r); linear_shaker(); long long pos=1,last=0; while (pos<=(r/k)) { long long ret1=(r/k)/((r/k)/pos),ret2; if (!((l-1)/(k*pos))) ret2=inf; else ret2=((l-1)/k)/(((l-1)/k)/pos); last=min(ret1,ret2); ret1=(ask(last)-ask(pos-1));ret2=f_pow(r/(k*pos)-(l-1)/(k*pos),n); ans+=((ask(last)-ask(pos-1))*f_pow(r/(k*pos)-(l-1)/(k*pos),n))%mod; if (ans<mod) ans=(ans+mod)%mod; pos=last+1; } printf("%lld ",(ans+mod)%mod); return 0; }