好数 - 折半搜索

题目大意:
给你个质数集合S, S 25 |S|\le25 ,问有多少不超过n的数字其质因数分解的质因子都在S中。
题解:
直接折半爆搜即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
const int K=28,N=10000000;lint n,lst1[N],lst2[N],ans,ans2;int p[K],p1[K],p2[K];
inline int dfs(int *p,int x,int c,lint v,lint *lst,int &lc)
{
    if(x==c+1) return lst[++lc]=v,0;
    lint w=n/v;dfs(p,x+1,c,v,lst,lc);
    while(w>=p[x]) w/=p[x],dfs(p,x+1,c,v*=p[x],lst,lc);
    return 0;
}
inline int solve(int *p,int c,lint *lst,int &lc)
{   return lc=0,dfs(p,1,c,1,lst,lc),sort(lst+1,lst+lc+1),0; }
int main()
{
    int k,c1=0,c2=0,lc1,lc2;scanf("%d%lld",&k,&n);
    rep(i,1,k) scanf("%d",&p[i]);sort(p+1,p+k+1);
    int t=5;
    if(k<=2*t)
    {
        rep(i,1,t) p1[++c1]=p[i];
        rep(i,t+1,k) p2[++c2]=p[i];
    }
    else{
        rep(i,1,t) p1[++c1]=p[i],p1[++c1]=p[k-i+1];
        rep(i,t+1,k-t) p2[++c2]=p[i];sort(p1+1,p1+c1+1);
    }
    solve(p1,c1,lst1,lc1),solve(p2,c2,lst2,lc2);
    for(int i=1,j=lc2;i<=lc1;ans+=j,(j?ans2=max(ans2,lst1[i]*lst2[j]):0),i++)
        while(j&&!(lst1[i]<=n/lst2[j])) j--;
    return !printf("%lld\n%lld\n",ans2,ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83715434
今日推荐