【51nod】【算法马拉松14】1586 约数和

传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1586

题面:

有三个下标从 1 1 1 n n n的数组 a 、 b 、 c a、b、c abc a a a数组初始全为0。

b [ i ] = ∑ j ∣ i a [ j ] b[i]=\sum\limits_{j|i}a[j] b[i]=jia[j]
c [ i ] = ∑ j ∣ i b [ j ] c[i]=\sum\limits_{j|i}b[j] c[i]=jib[j]

需要进行下列操作:
1 x x x y y y :将 a [ x ] a[x] a[x]加上 y y y
2 x x x :询问当前 c [ x ] c[x] c[x]的值

Input
第一行两个整数, n n n q q q,分别表示数组下标范围和操作次数。( 1 < = n , q < = 1 , 000 , 000 1<=n,q<=1,000,000 1<=n,q<=1,000,000
接下来 q q q行,描述一个操作。( x x x随机, 1 < = x < = n 1<=x<=n 1<=x<=n, 1 < = y < = 1 0 6 1<=y<=10^6 1<=y<=106)

Output
对于每一个第二种操作输出一个答案。

对于每个 a a a数组元素,对它的下标整数倍b数组元素产生贡献,然后再对其下标整数倍的 c c c数组元素产生影响。
那么对于 a [ x ] a[x] a[x] c [ y ] c[y] c[y],通过简单的推算就可以知道 a [ x ] a[x] a[x] c [ y ] c[y] c[y]的贡献倍数为 y x \frac{y}{x} xy的约数个数倍
(可以理解为从 x x x y y y有多少种变换方法)
然后就可以使用正常的方法去维护了(本题单点查改,不需要数据结构维护)

于是预处理 1000000 1000000 1000000以内每个数的约数个数。
维护的方法有两种
第一种:每修改一个 a a a,就修改其所有相关的 c c c
第二种:每查询一个 c c c,就查询其所有相关的 a a a

因为n的约数个数是 n \sqrt{n} n 级别的,所以说,然而一个数的倍数可能是 n n n级别的
于是乎,一般情况下都会选择第二种维护方式(每次查询 n \sqrt{n} n ),这么想的同学应该在 51 n o d 51nod 51nod上从第 13 13 13个点开始挂……( 2500 m s 2500ms 2500ms左右跑过时间最长点)

这一道题中有个重要条件: x x x随机

这也就意味着,对于第二种维护方式,还是每次查询 n \sqrt{n} n 的期望查询次数。但是对于第一种维护方式,每次修改的期望修改次数只有 log ⁡ n \log n logn

于是这题选择第一种维护方式更优(快了不是一点),有人说这题读入输出优化一个不能少,少一个就T。然后……我就华丽丽地一个都没加……硬是过了这题……( 1300 m s 1300ms 1300ms

#include<stdio.h>
#define N 1000050
#define LL long long

LL ans,a[N];
int f[N],n,q,c,tot,U;

int main()
{
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;i++) for (int j=i;j<=n;j+=i) f[j]++;
    for (int c;q;q--)
    {
        scanf("%d",&c);
        if (c==1) 
        {
            scanf("%d%d",&U,&c);
            for (int i=U,j=1;i<=n;i+=U,j++) a[i]+=c*f[j];
        }
        else 
        {
            scanf("%d",&c);
            printf("%I64d\n",a[c]);
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值