码迷,mamicode.com
首页 > 其他好文 > 详细

p3172 选数

时间:2018-12-09 11:59:47      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:font   mod   while   style   time   using   targe   技术分享   分块   

传送门

分析

技术分享图片

对这个$f(k)$整除分块,用杜教筛搞出$\mu$的部分然后另一部分快速幂即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int N = 5e6;
const int mod = 1e9+7;
int p[N+10],mu[N+10];
bool is[N+10];
map<int,int>MU;
inline void init(){
    int i,j,cnt=0;
    mu[1]=1;
    for(i=2;i<=N;i++){
      if(!is[i])p[++cnt]=i,mu[i]=-1;
      for(j=1;j<=cnt,i*p[j]<=N;j++){
          is[p[j]*i]=1;
          if(i%p[j]==0){
            mu[p[j]*i]=0;
            break;
          }
          mu[p[j]*i]=-mu[i];
      }
    }
    for(i=2;i<=N;i++)mu[i]=(mu[i]+mu[i-1]+mod)%mod;
}
inline int go(int x){
    if(x<=N)return mu[x];
    if(MU[x])return MU[x];
    int res=1,le=2,ri;
    for(;le<=x;le=ri+1){
      ri=x/(x/le);
      res=(res-(long long)(ri-le+1)*go(x/le)%mod+mod)%mod;
    }
    return MU[x]=res;
}
inline int pw(int x,int p){
    int res=1;
    while(p){
      if(p&1)res=(long long)res*x%mod;
      x=(long long)x*x%mod;
      p>>=1;
    }
    return res;
}
int main(){
    int n,m,p,k,L,R,le=1,ri,Ans=0;
    scanf("%d%d%d%d",&p,&k,&L,&R);
    n=R/k,m=(L-1)/k;
    init();
    for(;le<=n;le=ri+1){
      if(m/le)ri=min(n/(n/le),m/(m/le));
        else ri=n/(n/le);
      Ans=(Ans+(long long)(go(ri)-go(le-1)+mod)%mod*pw(n/le-m/le,p)%mod)%mod;
    }
    printf("%d\n",Ans);
    return 0;
}

p3172 选数

标签:font   mod   while   style   time   using   targe   技术分享   分块   

原文地址:https://www.cnblogs.com/yzxverygood/p/10090363.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!