6069 筛法

求给出l,r,k,求累加和d[i^k](i=[l~r]),其中 d(i):i 的因子个数 ,l,r<=1e12,k<=1e7,r-l<=1e6
n=a1^p1*a2^p2..an^pn 则因子个数为 (p1+1)*(p2+1)*..(pn+1)
n^k的因子数为(p1+k+1)*..(pn+k+1)
n的素因子<=sqrt(n),先晒出sqrt(r)内的素因子,对[l,r]每个数分解出其素因子的幂即可(用一个素数去更新它倍数的幂.)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+20;
const int M=1e6;
const ll mod=998244353;
ll L,R,k,T,f[N],pw[N],vis[N],p[N],pn=0;
void init()
{
    for(int i=2;i<=M;i++)
    {
        if(!vis[i])
        {
            p[pn++]=i;
            for(int j=i+i;j<=M;j+=i)
                vis[j]=1;
        }
    }
}
int main()
{
    init();
    cin>>T;
    while(T--)
    {
        ll ans=0;
        scanf("%lld%lld%lld",&L,&R,&k);
        if(L==1)
            ans++,L++;
        for(ll i=L;i<=R;i++)
            f[i-L]=i,pw[i-L]=1;
        for(int i=0;i<pn&&p[i]*p[i]<=R;i++)
        {
            //p[i]μ?±?êy?aê?
            ll st=L,cnt;
            if(L%p[i])
                st=(L/p[i]+1)*p[i];
            for(ll j=st;j<=R;j+=p[i])
            {
                cnt=0;
                while(f[j-L]%p[i]==0)
                    cnt++,f[j-L]/=p[i];
                pw[j-L]=(pw[j-L]*(cnt*k+1))%mod;
            }
        }
        for(ll i=L;i<=R;i++)
        {
        //    cout<<i<<‘ ‘<<pw[i-L]<<endl;
            if(f[i-L]==1)
                ans=(ans+pw[i-L])%mod;
            else//该数为素数
                ans=(ans+pw[i-L]*(k+1))%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-11-03 03:26:59

6069 筛法的相关文章

HDU 6069 Counting Divisors(区间素数筛法)

题意:...就题面一句话 思路:比赛一看公式,就想到要用到约数个数定理 约数个数定理就是: 对于一个大于1正整数n可以分解质因数: 则n的正约数的个数就是 对于n^k其实就是每个因子的个数乘了一个K 然后现在就变成了求每个数的每个质因子有多少个,但是比赛的时候只想到sqrt(n)的分解方法,总复杂度爆炸,就一直没过去,然后赛后看官方题解感觉好妙啊! 通过类似素数筛法的方式,把L - R的质因子给分解,就可以在O(nlogn)的时间之内把所以的数给筛出来. 代码: /** @xigua */ #i

HDOJ 6069 素数筛法(数学)

Counting Divisors Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3041    Accepted Submission(s): 1130 Problem Description In mathematics, the function d(n) denotes the number of divisors of

线性筛法

关于线性筛法 线性是指O(n)内筛掉所有合数,还有一种方法叫埃氏筛法,我先证明埃氏筛法效率低,也就是会有重复. 证明如下: 埃氏筛法的原理是找到一个素数后,它的1~n倍就会被筛掉,任何一个合数都可以被拆成一个质数*合数的形式,我们对每一个质数对应的可能的(合)数都枚举了,这就保证了所有可能的合数都被筛掉了.为什么不是最优呢?问题出在那个质数上,对于一个合数m,m=h*P,P是质数且P>m的最小质因数,那么m也可以表示为m=H*p,(H是个比h大的合数,p是m的最小质因数),这样我们在枚举p的倍数

HDU 5211 筛法求约数

给出n个数a1,a2...an,定义函数 f[i]=j,(i<j),表示aj mod ai=0 的最小j,其中j大于i,如果不存在这样的数,则f[i]=0 求n个数所有f[]值的和 先用筛法o(nlogn)求出每个数的约数 然后每读入一个数x,先找出所有的约数,再看看之前有没有出现过这些约数. 这个回看的过程可以用一个数组维护. 维护watch[],watch[aj]=j 表示aj还没有找到函数值,如果aj是x的约数,那么说明aj的函数值为x的位置. #include<cstdio> #

POJ 2689 Prime Distance(素数区间筛法--经典题)

大致题意:给定[L,R]区间,找出区间内的每个素数 数据范围 : 1<=L< R<=2,147,483,647) R-L <=1,000,000. R的数值太大,所以不能直接筛[0,R]的,要空间和时间优化,用到区间筛法,另外注意不能用int,因为R和L都是满int的,中间有很多细节处理会爆int的,还要注意1不是素数,所以在区间筛中要特判一下,是个易错的地方 //1160K 16MS C++ 1539B #include<cstdio> #include<ios

Counting Divisors HDU - 6069

Counting Divisors HDU - 6069 题意:给定区间[a,b]和k,求xk有多少因子(x属于[a,b]),求和. 题解:http://blog.csdn.net/zlh_hhhh/article/details/76680641 a.b最大可达到1e12,但是b-a<1e6. 一开始愚蠢的一个一个分解然后去求有多少因子然后求和,范围那么大裸裸的超时啊! 可以枚举素数,对每一个素数,把区间内所有可以分解的进行分解. 最后再求和. 1 #include <bits/stdc++

hdu6069[素数筛法] 2017多校3

/*hdu6069[素数筛法] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; LL l, r, k; const LL MOD = 998244353LL; int T, n, prime[1100000], primesize; bool isprime[11000000]; void getlist(int listsize) { memset(isprime, 1, sizeof

2017省夏令营Day7 【快速幂,筛法,矩阵快速幂,线段树】

题解:首先,我们可以得到一个规律:经过2次变换后,a和b的值都分别乘2了,所以只要用快速幂就能过啦,但是,要特判n为0的情况. 代码如下: 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define Mod 1000000007 5 using namespace std; 6 long long a,b,n,ans1,ans2; 7 long long power(long long x)

2015 HDU 多校联赛 5317 RGCDQ 筛法求解

2015 HDU 多校联赛 5317 RGCDQ 筛法求解 题目  http://acm.hdu.edu.cn/showproblem.php? pid=5317 本题的数据量非常大,測试样例多.数据量大, 所以必须做预处理.也就是用筛法求出全部的F[x],将全部F[x] 打印出来发现.事实上结果不大,最大的数值是7.所以对于每一个区间询问, 直接暴力求取有多少个 1 2 3 4 5 6 7 就可以,从大到小查找.假设出现2个以上 3-7 的数值,那么最大公约数就是该数字. 假设没有出现两个反复