Description
如果一个正整数的所有质因子都小于等于m且每种质因子个数都为奇数,则称这个数为幸运数,例如当m=3时,6是幸运数而5不是,12也不是幸运数(2这个质因子有偶数个)。
给定n,m,求小于等于n的幸运数有多少个。
Input
一行2个数,表示n,m。
Output
一行1个数,表示幸运数的个数。
Sample Input
10 3
Sample Output
5
Data Constraint
对于20%的数据,n<=104,m<=104;
对于40%的数据,n<=107,m<=106;
对于80%的数据,n<=108,m<=106;
对于100%的数据,n<=109,m<=106。
思路
首先,分解质因数,然后dfs枚举因子个数。结果TLE20
所以考虑优化。
我们发现,当x*a[i]^2>m那么可以二分找出那些质数合法
代码
#include<iostream>
#include<cstdio>
#define sqr(x) (x*x)
#define ll long long
using namespace std;
int n,m,g[1000010],f[1000010],cnt,ans;
void ef(int x,int t)
{
int l=x,r=cnt,mid,p=-1;
while (l<=r)
{
mid=(l+r)>>1;
if (t*(ll)g[mid]<=n) p=mid,l=mid+1; else r=mid-1;
}
if (p!=-1) ans+=p-x+1;
ans++;
}
void dfs(int x,int t)
{
if (x>cnt){ ans++; return; }
if (t*(ll)g[x]*g[x]>n) { ef(x,t); return; }
dfs(x+1,t);
ll k=g[x];
for (int i=1;i<=50;i++)
{
if (t*k<=n) dfs(x+1,t*k); else break;
k*=sqr(g[x]);
}
}
int main()
{
scanf("%d%d",&n,&m),m=min(n,m);
for (int i=2;i<=m;i++)
{
if (!f[i]) g[++cnt]=i;
for (int j=1;j<=cnt&&(ll)i*g[j]<=m;j++)
{
f[i*g[j]]=1;
if (i%g[j]==0) break;
}
}
dfs(1,1);
printf("%d",ans);
}