题意
求 (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),'
');
}
}