HDU -- 6069 Counting Divisors 【思维 + 二次筛法】多校第四场1003

传送门
//题意就不说了.
//思路:首先这个应该可以推到.这里写图片描述
所以可以发现这个k次方是没有什么影响的, 还是直接求质因子连乘就是了.
//问题的关键在于如何在可行的复杂度中求出区间中每一个数的质因子连乘的幂. n√n的复杂度绝对不行, 所以我们选用类似于区间筛的方法处理. 这样复杂度就大约在nlogn, 因为这个是区间求质因子个数, 与单数求质因子个数肯定不同赛.

AC Code

/** @Cain*/
const ll mod = 998244353;
const int maxn=1e6+5;
ll L,R,k;
bool ispri[maxn];
ll pri[maxn];
ll p;
void sieve()  //预处理1e6以内的素数,连乘也够了.
{
    Fill(ispri,true);
    ispri[0] = ispri[1] = false;
    p = 0;
    for(ll i=2;i<maxn;i++){
        if(ispri[i]){
            pri[p++] = i;
            for(ll j=i*2;j<maxn;j+=i){
                ispri[j] = false;
            }
        }
    }
}

ll f[maxn], cnt[maxn];
//f保存当前这个值(也用来判断幂),cnt是每一个数的方案数.
void solve()
{
    scanf("%lld %lld %lld",&L,&R,&k);
    ll res = 0;
    for(int i=0;i<=R-L;i++) f[i] = L+i,cnt[i] = 1;
    for(ll i=0; i<p && pri[i]*pri[i] <= R ; i++){
        ll tmp = L;  //假设从L开始扫
        if(L % pri[i]) tmp = (L/pri[i]+1)*pri[i];  
        //如果当前这个素数不是因子就从最近的开始枚举.
        //否则一个数会被多次算入.
        for(ll j=tmp;j<=R;j+= pri[i]){
            ll ans = 0;   //将L-R所有的可以被当前pri[i]除尽的数筛掉.
            while(f[j-L] % pri[i] == 0){
                f[j-L] /= pri[i];
                ans++;  //算幂.
            }
            cnt[j-L] = cnt[j-L]*(k*ans+1) % mod; //保存方案数
        }
    }
    for(int i=0;i<=R-L;i++){
        if(f[i] != 1) res = (res + cnt[i]*(k+1) ) % mod;
        //如果当前知不是1,表示最后一次除完还剩一个较大的素数.
        //所以次数需要再乘一下.
        else res = (res + cnt[i]) % mod;
        //否则就是被除尽的了, 剩下1不用管.
    }
    printf("%lld\n",res);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值