每日一题 CF83D Numbers 题解

首先我们发现要记录的东西可以搞成一个最小表示法来记录
我们只需要把这个最小的k作为表示方案就可以了
然后具体的我们每次求这个答案需要递归容斥下去
首先要是能被k整除的,其次我们把小于k的方案减去即可
具体我们写个calc函数然后不断递归就可以了!
细节是我们要判断一下不是质数的情况直接return 0
我们可以先筛除小于1e6的质数,剩下的暴力判断,再加上记忆化,总复杂度O(能过)
代码:

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr<<#x<<" = "<<x
#define sp <<"  "
#define el <<endl
#define fgx cerr<<" ------------------------------------------------ "<<endl
#define LL long long
#define DB double
#define mpt make_pair
#define pb push_back
inline int read(){
    int nm=0; bool fh=true; char cw=getchar();
    for(;!isdigit(cw);cw=getchar()) fh^=(cw=='-');
    for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    return fh?nm:-nm;
}
#define M 1000200
#define MAXN 1000000
int pri[M],cnt; bool np[M];
unordered_map<int,int>Hv;
inline bool check(int x){
    if(x<=MAXN) return np[x]^1;
    if(Hv[x]) return Hv[x]>0;
    for(int i=2;i*i<=x;i++) if(x%i==0){
        Hv[x]=-1; return false;
    } Hv[x]=1; return true;
}
inline int gt(int x,int k){
    if(!check(k)) return 0;
    int all=x/k,R=min(k-1,x/k);
    for(int i=2;i<=R;i++) all-=gt(x/k,i);
    return all;
}

int main(){
    for(int i=2;i<=MAXN;i++){
        if(!np[i]) pri[++cnt]=i;
        for(int j=1;j<=cnt&&i*pri[j]<=MAXN;j++){
            np[i*pri[j]]=true;
            if(i%pri[j]==0) break;
        }
    }
    int l=read(),r=read(),K=read();
    printf("%d\n",gt(r,K)-gt(l-1,K));
    return 0;
}
全部评论

相关推荐

评论
点赞
收藏
分享
牛客网
牛客企业服务