简单的函数题解

简单的函数题解

一个数\(x\),其\(f[x]=f[y]+1\)
\(lcm[y]=gcd(1,2,3,4,...,y)\)
则当且仅当\(lcm[y-1] \mid x,lcm[y] \nmid x\)
所以区间内答案为\(f[x]+1\)的为\(lcm[y-1]\)的倍数个数\(-lcm[y]\)的倍数个数
我们发现\(lcm[43]>=10^{18}\)
所以预处理出\(f[2]~f[43]\)
再统计\(f[x]=i\)\(x\)个数,
最后快速幂求解。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=56; 
const ll mod=1e9+7;
ll n,t,f[M],lcm[M],cnt[M],ans=1;
ll num(ll l,ll r,ll x){return r/x-(l-1)/x;}
ll ksm(ll base,ll v){
   ll answer=1;
   while(v){
      if(v&1) answer=answer*base%mod;
      base=base*base%mod,v>>=1; 
   }
   return answer;
}
ll gcd(ll u,ll v){return !v?u:gcd(v,u%v);}
int main(){
    scanf("%lld",&n),f[2]=1,lcm[1]=1,t=2;
    for(ll i=2;i<=43;++i){
        t=i,lcm[i]=lcm[i-1]/gcd(lcm[i-1],i)*i;
        if(lcm[i]>=n) break;
    }
    for(int i=3;i<=43;++i) for(int j=2;j<i;++j) if(i%j){f[i]=f[j]+1; break;}
    for(int i=2;i<=t;++i) cnt[f[i]+1]+=num(t+1,n,lcm[i-1])-num(t+1,n,lcm[i]);
    for(int i=2;i<=t;++i) ++cnt[f[i]];
    for(int i=2;i<=5;++i) ans=ans*ksm(i,cnt[i])%mod;
    printf("%lld\n",ans);
    return 0;
}  
posted @ 2019-10-31 16:29  lsoi_ljk123  阅读(158)  评论(0编辑  收藏  举报