Hdu6069 Counting Divisors(2017多校第4场)

14 篇文章 0 订阅
7 篇文章 0 订阅

Counting Divisors

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1105    Accepted Submission(s): 393


Problem Description
In mathematics, the function  d(n)  denotes the number of divisors of positive integer  n .

For example,  d(12)=6  because  1,2,3,4,6,12  are all  12 's divisors.

In this problem, given  l,r  and  k , your task is to calculate the following thing :

(i=lrd(ik))mod998244353

 

Input
The first line of the input contains an integer  T(1T15) , denoting the number of test cases.

In each test case, there are  3  integers  l,r,k(1lr1012,rl106,1k107) .
 

Output
For each test case, print a single line containing an integer, denoting the answer.
 

Sample Input
  
  
3 1 5 1 1 10 2 1 100 3
 

Sample Output
  
  
10 48 2302
 

Source
 

Recommend
liuyiding
—————————————————————————————————
题目的意思是求一个区间的每个数的因子数之和
思路:先去打一个1到1e6的素数表,然后去枚举每个素数在区间内的倍数,可以跳着枚举,计算出每个数对应的因子个数,对于每个数的因子个数就等于枚举的因子个数*k+1累乘起来,注意剩下的大素数的判断
比赛是也是素数打表枚举的 ,鬼知道怎么想的去枚举区间的每个数去求因子,妥妥TLE,也有过正解的想法,想过没想太透彻,感觉这种题值得好好反思警戒自己
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
const LL mod = 998244353;

bool vis[1000009];
LL prime[1000009], sum[1000009], a[1000009];
LL l, r, k;
int cnt;

void init()
{
    memset(vis, true, sizeof vis);
    vis[0] = vis[1] = false;
    cnt = 0;
    for (int i = 2; i < 1000009; i++)
    {
        if (!vis[i]) continue;
        prime[cnt++] = i;
        for (int j = i * 2; j < 1000009; j += i) vis[j] = false;
    }
}

int main()
{
    init();
    int t;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%lld%lld%lld", &l, &r, &k);
        for (int i = 0; i <= r - l; i++) sum[i] = 1, a[i] = i + l;
        LL ans = 0;
        for (int i = 0; i < cnt; i++)
        {
            LL p = (l / prime[i] + (l%prime[i] ? 1 : 0))*prime[i];
            for (LL j = p; j <= r; j += prime[i])
            {
                int res = 0;
                while (a[j - l] % prime[i] == 0) res++, a[j - l] /= prime[i];
                sum[j - l] = sum[j - l] * ((1LL * res*k + 1) % mod) % mod;
            }
        }
        for (int i = 0; i <= r - l; i++)
        {
            if (a[i] != 1) sum[i] = sum[i] * (k + 1) % mod;
            ans = (ans + sum[i]) % mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值