【题解】[HDU 7080] Pty hates prime numbers | 20210928 模拟赛 质数(prime)【容斥】

题目链接

题目链接Vjudge

题意

(n) 以内有多少个数没有 (p_k) 以内的数作为质因子。(nleq 10^{18},kleq 16)(10^5) 组询问。

题解

朴素做法为容斥。考虑 (nleq 6 imes 10^5,kleq 7) 时答案可以预处理,由于有循环节只要 (kleq 7) 即可 (O(1)) 计算;剩下 9 个质数可以 (2^9) 枚举。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int BUF_LEN=1<<19;
struct FastIO{
    char bufi[BUF_LEN+10],*PTi=bufi+BUF_LEN,*PTENDi=bufi+BUF_LEN;
    inline char gc(){
        (PTi==PTENDi)&&(bufi[fread(bufi,1,BUF_LEN,stdin)]=0,PTi=bufi);
        return *(PTi++);
    }
    char bufo[BUF_LEN+10],*PTo=bufo,*PTENDo=bufo+BUF_LEN;
    inline void pc(char c){
        (PTo==PTENDo)&&(fwrite(bufo,1,BUF_LEN,stdout),PTo=bufo);
        *(PTo++)=c;
    }
    void flush(){
        fwrite(bufo,1,PTo-bufo,stdout);
        PTo=bufo;
    }
    ~FastIO(){
        flush();
    }

    template<class T>inline void getint(T &x=0){
        char c=gc();
        int f=1;x=0;
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;
            c=gc();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0'; 
            c=gc();
        }
        if(f==-1)x=-x;
    }
    operator int(){
        int v;getint(v);return v;
    }
    operator long long(){
        long long v;getint(v);return v;
    }
    template<class T>inline void putint(T x=0,char sep=' '){
        char tmp[20],len=0;
        if(x<0)pc('-'),x=-x;
        if(x==0){ pc('0');pc(sep);return; }
        while(x)tmp[len++]=x%10,x/=10;
        for(int i=len-1;~i;--i)pc(tmp[i]|'0');
        pc(sep);
    }
}io;

const int M=6e5,K=7;
int pri[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
ll prd[16];
bool b[M+10];
int s[K][M+10];

ll n;
int k;

int qaq=0;
inline ll _(ll x,int k){
	int p=prd[k];
	return s[k][p]*(x/p)+s[k][x%p];
}
ll ss(ll x,int k,int sign){
	if(!k)return x*sign;
	if(k<=K)return _(x,k-1)*sign;
	ll ans=0;
	for(int S=0;S<1<<(k-K);S++){
		ll y=1;
		int sign=1;
		for(int j=0;j<k-K;j++)if((S>>j)&1)y*=pri[K+j],sign=-sign;
		ans+=sign*_(x/y,K-1);
	}
	return ans;
}

ll qn[100010],qk[100010],ans[100010];
vector<int> p[17];
int main(){
	prd[0]=2;for(int i=1;i<16;i++)prd[i]=prd[i-1]*pri[i];
	for(int i=0;i<K;i++){
		int p=pri[i];
		for(int j=p;j<=M;j+=p)
			b[j]=1;
		int *si=s[i];
		for(int j=1;j<=M;j++)
			si[j]=si[j-1]+!b[j];
	}

	int T=io;
	while(T--){
		ll n=io,k=io;
		io.putint(ss(n,k,1),'
');
	}
}
 

知识共享许可协议
若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
原文地址:https://www.cnblogs.com/wallbreaker5th/p/15349885.html