UVA11876 N + NOD (N)【欧拉筛法+前缀和】

自闭症网瘾萝莉.ら 提交于 2020-04-20 05:22:47

Consider an integer sequence N where,
N0 = 1
Ni = Ni−1 + NOD(Ni−1) for i > 0
在这里插入图片描述
    Here, NOD(x) = number of divisors of x.
    So the first few terms of this sequence are 1 2 4 7 9 12 18

    Given two integers A and B, find out the number of integers in the above sequence that lies within the range [A, B].
Input
The first line of input is an integer T (T < 100000), that indicates the number of test cases. Each case contains two integers, A followed by B (1 ≤ A ≤ B ≤ 1000000).
Output
For each case, output the case number first followed by the required result.
Sample Input
3
1 18
1 100
3000 4000
Sample Output
Case 1: 7
Case 2: 20
Case 3: 87



















问题链接UVA11876 N + NOD (N)
问题简述:给定公式Ni = Ni-1 + NOD(Ni-1),NOD为因子个数,求一个区间[A,B]上有多少个N。
问题分析:用欧拉筛法得到素数备用,打表计算函数的前缀和,然后查表计算。
程序说明:数组sum[]是前缀和。
参考链接:(略)
题记:(略)




AC的C++语言程序如下:

/* UVA11876 N + NOD (N) */

#include <bits/stdc++.h>

using namespace std;

const int N = 1000000;
bool isprime[N + 1];
int prime[N / 3], pcnt = 0;
// 欧拉筛法
void eulersieve(void)
{
    memset(isprime, true, sizeof(isprime));

    isprime[0] = isprime[1] = false;
    for(int i = 2; i <= N; i++) {
        if(isprime[i])
            prime[pcnt++] = i;
        for(int j = 0; j < pcnt && i * prime[j] <= N; j++) {  //筛选
            isprime[i * prime[j]] = false;
            if(i % prime[j] == 0) break;
        }
    }
 }

int ni[N + 1], sum[N + 1];

int nod(int n)
{
    map<int, int> m;
    for(int i = 0; i < pcnt; i++) {
        if(n < prime[i]) break;
        else if(n % prime[i] == 0) {
            int cnt = 0;
            while(n % prime[i] == 0)
                cnt++, n /= prime[i];
            m[prime[i]] = cnt;
        }
    }
    if(n != 1) m[n] = 1;

    int ret = 1;
    for(map<int, int>::iterator iter = m.begin(); iter != m.end(); iter++)
        ret *= iter->second + 1;

    return ret;
}

void maketab()
{
    int ncnt = 0;
    ni[ncnt++] = 1;
    sum[0] = 0;
    sum[1] = ni[1];
    for(;;) {
        int n = ni[ncnt - 1];
        int ni2 = n + nod(n);
        if(ni2 > N) {
            fill(&sum[n], &sum[N + 1], ncnt);
            break;
        } else {
            fill(&sum[n], &sum[ni2], ncnt);
            ni[ncnt++] = ni2;
        }
    }
}

int main()
{
    eulersieve();

    maketab();

    int t, a, b;
    scanf("%d", &t);
    for(int k = 1; k <= t; k++) {
        scanf("%d%d", &a, &b);
        printf("Case %d: %d\n", k, sum[b] - sum[a - 1]);
    }

    return 0;
}
发布了2286 篇原创文章 · 获赞 2373 · 访问量 265万+
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!