game with numbers

给定大小为 n n n的集合 S S S
一个数被称作合法的,当且仅当 x S x∈S xS或者 x x x存在大于1的真因数,且这些真因数均是合法的
求有多少个数 x x x满足 2 x m 2≤x≤m 2xm x x x合法
PS: x x x的真因数指不是 x x x本身的约数

T组数据
每组数据给定 n m n和m nm
接下来一行 n n n个数字,表示集合 S S S

思路:先将范围内所有数的真因数个数统计出来。若某个数是质数,就将它的因数个数定位INF,便于与题意符合。然后利用给定的 n n n个数进行因数的筛除,若某个数的因数被完全筛除,则表明这个数满足条件。

//#pragma comment(linker, "/STACK:102400000,102400000") 
#include "bits/stdc++.h"
#define pb push_back
#define ls l,m,now<<1
#define rs m+1,r,now<<1|1
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0', c=getchar();
    return x;
}

const int maxn = 3e5+10;
const int mod = 1e9+7;
const double eps = 1e-9;

int n, m;
int cnt[maxn];

void solve() {
    memset(cnt,0,sizeof(cnt));
    for(int i=2; i<maxn/2; ++i) {
        for(int j=2*i; j<maxn; j+=i) cnt[j]++;  //统计因数个数
    }
    for(int i=2; i<maxn; ++i) if(cnt[i]==0) cnt[i]=1e9; //质数的特殊处理
    n=read(), m=read();
    for(int i=0; i<n; ++i) cnt[read()]=0; //这些数为合法数
    int ans=0;
    for(int i=2; i<=m; ++i) {
        if(cnt[i]<=0) { //表明这个数是合法的
            ans++; 
            for(int j=2*i; j<=m; j+=i) cnt[j]--; //利用合法数进行后续的数的因数的筛除
        }
    }
    cout<<ans<<endl;
}

int main() {
    //ios::sync_with_stdio(false);
    int T=read();
    while(T--) solve();
}