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);
}