杜教筛

51nod1244-------杜教筛入门

这几天开始学习杜教筛,前前后后看了大约一周,现在终于看懂了,感受到了自己的弱小,哈哈。
这里不详细写了就,等区域赛回来给我的大一小孩讲一下。
这里先贴上我学习的博客,感觉对数学要求和抽象思维能力要求很高

感谢一下各位大佬
传送门
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;
}

你可能感兴趣的:(数论)