# 【bzoj3930】[CQOI2015]选数 莫比乌斯反演+杜教筛

2 2 2 4

3

#include <cstdio>
#include <map>
#define N 1000010
#define mod 1000000007
using namespace std;
typedef long long ll;
const int m = 1000000;
map<int , int> f;
map<int , int>::iterator it;
int mu[N] , sum[N] , prime[N] , tot;
bool np[N];
ll pow(ll x , int y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int query(int n)
{
if(n <= m) return sum[n];
it = f.find(n);
if(it != f.end()) return it->second;
int i , last , ans = 1;
for(i = 2 ; i <= n ; i = last + 1) last = n / (n / i) , ans -= (last - i + 1) * query(n / i);
return f[n] = ans;
}
int main()
{
int i , j , p , k , l , r , last;
ll ans = 0;
mu[1] = sum[1] = 1;
for(i = 2 ; i <= m ; i ++ )
{
if(!np[i]) mu[i] = -1 , prime[++tot] = i;
for(j = 1 ; j <= tot && i * prime[j] <= m ; j ++ )
{
np[i * prime[j]] = 1;
if(i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else mu[i * prime[j]] = -mu[i];
}
sum[i] = sum[i - 1] + mu[i];
}
scanf("%d%d%d%d" , &p , &k , &l , &r) , r /= k , l = (l - 1) / k;
for(i = 1 ; i <= r ; i = last + 1)
{
last = r / (r / i);
if(l >= i) last = min(last , l / (l / i));
ans = (ans + (query(last) - query(i - 1) + mod) % mod * pow((ll)r / i - l / i , p) % mod) % mod;
}
printf("%lld\n" , ans);
return 0;
}


|转载请注明 [原文链接][作者] ，谢谢！

posted @ 2017-06-13 11:38  GXZlegend  阅读(403)  评论(1编辑  收藏  举报