【2017 Multi-University Training Contest - Team 4】Counting Divisors

Link:http://acm.hdu.edu.cn/showproblem.php?pid=6069

Description

定义d(i)为数字i的因子个数;
rld(ik)
其中l,r<=1012rl<=106

Solution

如果把一个数x质因数分解成p1a1p2a2...pnan
的形式;
可知数字x的因子个数为
(a1+1)(a2+1)...(an+1)
因为i还有k次方;
所以答案就是
(a1k+1)(a2k+1)...(ank+1)
需要对l..r里面所有的数字都进行质因数分解;
可以这样
先处理出2..r之间的所有素数;
然后枚举每个素数i它在l..r之间的倍数x;
则对x 用素数i进行质因数分解,也即一直除它;
这样,就能算出来x在质因数分解的时候,素数i最后的指数是多少了;
(累乘数字x的答案就好);
记录x在进行质因数分解的时候被除剩下的数字,除的时候是用
这个记录的数字除;
最后这个数字可能会不变;
因为它本身可能就是一个素数;
所以小于r的素数可能不是它的因子;
但是不可能还有大于r的因子;
所以如果除剩下的数字还大于0;
答案再乘上(k+1)就好;
最后把每个数字它的答案累加起来;
(一开始可以用O(n)的素数筛求出1..n之间的所有素数);

NumberOf WA

many times

Reviw

一开始一直往O(n14)的质因数分解想了;
没想到这种方法.
判断出某个素数是某个数的因子之后,不要再记录它的因子是什么了;
直接就开始质因数分解,这样比较快;
不然会超时.

Code

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define rs(x) scanf("%s",x+1)
#define oi(x) printf("%d",x)
#define ol(x) printf("%lld",x)
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e6;
const LL MOD = 998244353;

bool iszs[N+100];
vector <int> zsb;
LL num[N+100],ans[N+100];

int main(){
    //Open();
    //Close();
    ms(iszs,true);
    rep1(i,2,N)
    {
        if (iszs[i]) zsb.pb(i);
        int len = zsb.size();
        rep1(j,0,len-1)
        {
            int t = zsb[j];
            if (i*t>N) break;
            iszs[i*t] = false;
            if (i%t==0) break;
        }
    }

    int T;
    ri(T);
    while (T--){
        LL l,r,k;
        rl(l),rl(r),rl(k);
        for (LL i = l;i <= r;i++)
            num[i-l+1] = i,ans[i-l+1] = 1;

        rep1(i,0,(int) zsb.size()-1){
            LL x = zsb[i];
            if (x > r) break;
            LL temp = ((l-1)/x + 1)*x;
            for (LL i = temp;i <= r;i+=x){
                LL tot = i,cnt = 0;
                while (tot%x==0){
                    tot/=x;
                    num[i-l+1]/=x;
                    cnt++;
                }
                ans[i-l+1] = ans[i-l+1]*(cnt*k+1)%MOD;
            }
        }

        LL fans = 0;

        for (LL i = l;i <= r;i++){
            if (num[i-l+1]!=1){
                fans = (fans + ans[i-l+1]*(k+1)%MOD)%MOD;
            }else
                fans = (fans + ans[i-l+1])%MOD;
        }
        ol(fans);puts("");
    }
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(114)  评论(0编辑  收藏  举报