Hdu 6069

来源:互联网 发布:粒子群算法的具体应用 编辑:程序博客网 时间:2024/05/26 20:23

题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6069

题目大意:
给定区间[l,r]k

d(i)=d=1,d|nn1
求式子
i=lrd(ik)
的值,结果对998244353取模

分析:
区间长度为1e6,数据有10组以上,暴力分解整个区间的话,每个数的分解至多是logn级别的,而基于Miller_Robin的质因数分解polard_rho也只是O(n14)级别的,远远达不到要求,所以不能从对每个数分解质因数上想,而是试着用[2,r]内的所有质因子去筛[l,r]区间内的数,最后在除尽了这些因子后的数,要么是1,要么是一个大的质因子,且次数至多为1,因为如果大于sqrtr的因子次数大于1,这个数的大小就会大于r,产生矛盾

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;const ll mod = 998244353;const int maxn = 1e6+100;ll l,r,k;int len;bool isprime[maxn+200];int prime[maxn];ll divi[maxn];ll cnt[maxn];void init(){    for (int i =2 ; i <= maxn; i ++)    {        if (!isprime[i])        {            prime[++prime[0]] = i;            for (int j = i +i ; j <= maxn ; j+= i)                isprime[j] = true;        }    }}void solve(){    int st;    for (int i = 1 ; prime[i]<= r/prime[i] && i<= prime[0] ; i ++)    {        //printf("i = %d\n",prime[i]);        if (l%prime[i]==0)            st = 1;        else            st = 1 + (prime[i]-l%prime[i]);        for (int j = st ; j <= len ; j +=prime[i])        {            int ct = 0;            while (divi[j]%prime[i]==0)            {                divi[j]/=prime[i];                ct++;            }            cnt[j]*=(ct*k+1);            if (cnt[j]>=mod)                cnt[j] %= mod;        }    }    ll ans = 0;    for (int i =1 ; i <= len ; i ++)    {        if (divi[i]!=1)            cnt[i] = cnt[i] * (k+1)%mod;        //printf("divi[%d] = %lld\n",i,divi[i]);        ans += cnt[i];        if (ans>=mod)            ans %= mod;    }    printf("%lld\n",ans);}int main(){    init();    //printf("prime[0] = %d\n",prime[0]);    int T;    scanf("%d",&T);    while (T--)    {        scanf("%lld%lld%lld",&l,&r,&k);        len = (int)(r- l +1);        for (int i = 1 ; i <= len ; i ++)        {            divi[i] = l + i -1;            cnt[i] = 1;        }        solve();    }    return 0;}
原创粉丝点击