hdu 6069

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

每次做多校的题目,基本就是切水题,切完之后就挂机(真佩服那些神犇,什么都会做),毫无进度,这个题目找到过一道和这个很类似的题目

那个题目是用莫比乌斯反演做的,看了一下代码,完全看不懂,然后就放弃了。

其实之前也想到过枚举因数,但是碰到一个问题,就是觉得质数无法打表到1e12这么多,但是其实只需要打表到1e6就可以了

因为你到了如果这个最大的值也才1e12,所以如果这个数有个大于1e6的因子的话,那么说明这个因子只有一个。因为如果有两个的话,那么它肯定大于1e12了

但是做的时候这点没有想到,都是觉得要打表打到1e12,所以没能做

然后其实看了一下题解,然后确实感觉豁然开朗
只需要枚举一下质数,看看这个区间里面的这个质数有多少个

因为$x = p_{_{1}}^{k1}*p_{2}^{k2}*.....*p_{n}^{kn}$

所以x的因子个数n =$(k_{1}+1)*(k_{2}+1)*(k_{3}+1)*.....*(k_{n}+1)$

#include <stdio.h>
#define maxn 1000100
#define ll long long
#define mod 998244353
bool v[maxn];
ll p[maxn],tot = 0;
ll l,r,k,ans[maxn],num[maxn],n;

void init()
{
    for (int i = 2; i < maxn; i++) {
        if (!v[i])p[tot++] = i;
        for (int j = 0; j < tot&&i*p[j] < maxn; j++) {
            v[i*p[j]] = 1;
            if (i%p[j] == 0)break;
        }
    }
}

void Find(ll x)
{
    for(ll i = l/x*x;i<=r;i+=x)
    {
        if(i>=l)
        {
            int cnt = 0;
            while(num[i-l]%x==0)
            {
                num[i-l]/=x;
                cnt++;    //n次方
            }
            ans[i-l] = ans[i-l]*((ll)cnt*k+1)%mod;   //统计有多少个
        }
    }
}


void calc()
{
        scanf("%lld%lld%lld",&l,&r,&k);
        n = r - l;
        for(int i=0;i<=n;i++)
        {
            num[i] = i+l;
            ans[i] = 1;
        }
        for(int i = 0;i<tot;i++){
            if((ll)p[i]*p[i]>r)
                break;
            Find(p[i]);  //枚举质数
        }
}

int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        calc();
        long long a = 0;
        for(int i =0;i<=n;i++){
            if(num[i]>1)
                ans[i] = ans[i]*(k+1)%mod;     //大于1e6的只有一个,所以乘以k+1就可以了
a
= (a+ans[i])%mod; } printf("%lld ",a); } return 0; }
原文地址:https://www.cnblogs.com/Tree-dream/p/7285146.html