这几天开始学习杜教筛,前前后后看了大约一周,现在终于看懂了,感受到了自己的弱小,哈哈。
这里不详细写了就,等区域赛回来给我的大一小孩讲一下。
这里先贴上我学习的博客,感觉对数学要求和抽象思维能力要求很高
感谢一下各位大佬
传送门
http://jiruyi910387714.is-programmer.com/posts/195270.html
http://blog.csdn.net/skywalkert/article/details/50500009
https://blog.csdn.net/u014609452/article/details/54747368
第三个博客是个大佬,看了他的经历,发现自己真是蹉跎了岁月(虽然我知道知道这样用词不对,但是就是想用)
唉,算了。
代码是看的博客三的,
#include
#include
#include
#include
#include
using namespace std;
using namespace std::tr1;
const int MAXN = 1e6 ;
typedef long long LL;
LL prime[MAXN + 10];
int miu[MAXN + 10];
void pre() // 先预处理出一些miu
{
miu[1] = 1;
memset(prime,0,sizeof(prime));
for(int i = 2;i <= MAXN;++i)
{
if(!prime[i])
{
prime[++prime[0]] = i;
miu[i] = -1;
}
for(int j = 1;j <= prime[0] && prime[j] <= MAXN / i;j++)
{
prime[i * prime[j]] = 1;
if(i % prime[j] == 0)
{
miu[i * prime[j]] = 0;
break;
}
miu[i * prime[j]] = miu[i] * miu[prime[j]];
}
}
for(int i = 2;i <= MAXN;++i) miu[i] += miu[i - 1];
}
unordered_map M;
int sum(LL n)
{
LL ans = 1,l,r;
if(n <= MAXN) return miu[n];
if(M.find(n) != M.end()) return M[n];
for(l = 2;l * l <= n;++l) ans -= sum(n / l);
for(LL t = n / l; l <= n;l = r + 1,t--) // 将相同有的sum(t)的区间求出来,以加速计算
{
r = n / t;
ans -= (r - l + 1) * sum(t);
}
return M[n] = ans;
}
int main()
{
ios::sync_with_stdio(false);
LL a,b;
pre();
while(cin >> a >> b)
{
cout << sum(b) - sum(a - 1) << endl;
}
return 0;
}