HDU 6069 Counting Divisors(枚举区间)(素数筛模版)

来源:互联网 发布:淘宝指数在哪里看 编辑:程序博客网 时间:2024/06/05 21:00

本题两个关键点
1.要得知一个数有多少因子,假设他可以被分解为素因数
n = p1^c1*p2^c2+p3^c3…
那么他的因子数为(c1+1)(c2+1)+…+(ck+1).
好像他们又说这是个小学生都知道的结论T^T
2.假如我想要知道[l,r]区间内所有的因子数,不能像单一的一样单个扫描2,3,5,7…而是要2,扫l~r所有2的倍数,3扫,5扫,这样就不会浪费时间在扫一些大素数上.
最后的最后,分解时要忘记本身是大素数的情况!!!!

/*  xzppp  */#include <iostream>#include <vector>#include <cstdio>#include <string.h>#include <algorithm>#include <queue>#include <map>#include <string>#include <cmath>#include <bitset>#include <iomanip>using namespace std;#define FFF freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define MP make_pair#define PB push_back#define _ %MODtypedef long long  LL;typedef unsigned long long ULL;typedef pair<int,int > pii;typedef pair<LL,LL> pll;typedef pair<double,double > pdd;typedef pair<double,int > pdi;const int MAXN = 1e6+17;const int MAXM = 1e6+17;const int MAXV = 2*1e3+17;const int BIT = 15+3;const int INF = 0x7fffffff;const LL INFF = 0x3f3f3f3f3f3f3f3f;const int MOD = 998244353;int prime[1100000],primesize=0;bool isprime[11000000];void sieve(int listsize){    memset(isprime, 1, sizeof(isprime));    isprime[1] = false;    for(int i=2;i<=listsize;i++){        if(isprime[i]) prime[++primesize]=i;         for(int j = 1; j <= primesize && i*prime[j] <= listsize;j++){            isprime[i*prime[j]] = false;            if(i%prime[j] == 0) break;         }    }}LL sum[MAXN],rem[MAXN];int main(){    #ifndef ONLINE_JUDGE     FFF    #endif    sieve(1000000);    int t;    cin>>t;    while(t--)    {        LL l,r,k,ans = 0;        scanf("%lld%lld%lld",&l,&r,&k);        for (int i = 0; i < r-l+1; ++i)        {            sum[i] = 1;            rem[i] = i+l;        }        for (int i = 1; i <= primesize; ++i)        {            LL p = prime[i];            if(p>r) break;            LL beg = l/p *p ;            for (LL j = beg; j <= r; j+=p)            {                if(j<l) continue;                LL cnt = 0;                while(rem[j-l]%p==0)                {                    cnt++;                    rem[j-l]/=p;                }                sum[j-l] = (sum[j-l] * (k*cnt+1)_)_;            }        }        for (int i = 0; i < r-l+1; ++i)        {            if(rem[i]!=1) sum[i] = (sum[i]*(k+1)_)_;            ans = (ans + sum[i])_;        }        printf("%lld\n",ans );       }    return 0;}