HDU 6069 Counting Divisors

题目链接

思路:
先打一个从1到1e6的素数表,然后枚举不超过 r 的所有素数,然后再去枚举这些素数在l和r区间内的倍数,将其分解质因数,最后剩下的素数的c只可能是0或1,计算出每个数对应的因子个数,对于每个数的因子个数就等于枚举的因子个数*k+1累乘起来,最后加起来即可。
代码

# include 
using namespace std;
typedef long long LL;

const int N = 1e6+10;
const int Q = 998244353;

LL cnt [N], q[N], prime[N];
bool vis[N];

void init ()
{
    int tot = 0;
    for (int i=2; i<=N; ++i) {
        if (!vis[i]) {
            prime[tot++] = i;
        }
        for (int j=0; jint k = i * prime[j];
            if (k > N) break;
            vis[k] = 1;
        }
    }
}
void solve ()
{
    LL l, r, k, ans = 0;
    scanf("%lld%lld%lld", &l, &r, &k);
    if (l == 1) ans ++, l++;
    for (LL i = 0; i <= r-l; ++i) {
        cnt[i] = 1, q[i] = l+i;
    }
    for (LL i = 0; prime[i] * prime[i] <= r; ++i) {
        LL x = l / prime[i] + (l % prime[i] != 0);
        for (x *= prime[i]; x <= r; x += prime[i]) {
            LL cou = 0;
            while (q[x - l] % prime[i] == 0) {
                q[x - l] /= prime[i], cou++;
            }
            cnt [x - l] = (cnt [x - l] * ((cou * k) + 1)) % Q;
        }
    }
    for (LL i=0; i<=r-l; ++i) {
        if (q[i] != 1) ans = (ans + (k+1) * cnt[i]) % Q;
        else  ans = (ans + cnt[i]) % Q;
    }
    printf ("%lld\n", ans);
}

int main ()
{
    int T;
    init ();
    scanf ("%d", &T);
    while (T--) {
        solve ();
    }

    return 0;
}

你可能感兴趣的:(2017多校联合)